﻿using System;
using System.Globalization;
using System.Numerics;
using System.Text;
using ParserGenerator.Extensions;
using ParserGenerator.Output;

namespace ParserGenerator.Languages.CSharp
{
    partial class SyntaxTreeNodeWriter
    {
        #region tokens
        public virtual bool IsKeyword(string name)
        {
            if (name == null)
                throw new ArgumentNullException(nameof(name));
            return CSharpProgramParser.IsKeyword(name);
        }

        public virtual string EscapeKeyword(string name)
        {
            if (name == null)
                throw new ArgumentNullException(nameof(name));
            return "@" + name;
        }

        public virtual bool IsIdentifierLetter(char c)
        {
            return c == '_' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z';
        }

        public virtual bool IsIdentifierLetterOrDigit(char c)
        {
            return c == '_' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9';
        }

        public virtual bool IsSimpleIdentifier(string name)
        {
            if (name == null)
                throw new ArgumentNullException(nameof(name));
            if (!IsIdentifierLetter(name[0]))
                return false;
            for (int i = 1; i < name.Length; i++)
                if (!IsIdentifierLetterOrDigit(name[i]))
                    return false;
            return true;
        }

        public virtual string EscapeIdentifier(string name)
        {
            if (name == null)
                throw new ArgumentNullException(nameof(name));
            StringBuilder sb = new StringBuilder();
            int index = 0;
            foreach (int c in name.EnumCodepoints())
            {
                if (index == 0 && IsIdentifierLetter((char)c))
                    sb.Append((char)c);
                else if (index > 0 && IsIdentifierLetterOrDigit((char)c))
                    sb.Append((char)c);
                else if (0 <= c && c <= 0xFFFF)
                    sb.AppendFormat("\\u{0:X4}", c);
                else
                    sb.AppendFormat("\\U{0:X8}", c);
                index++;
            }
            return sb.ToString();
        }

        public virtual string EscapeCharacter(int c, char delimiter)
        {
            if (c < CharExtensions.MinChar || c > CharExtensions.MaxChar)
                throw new ArgumentOutOfRangeException(nameof(c), SR.InvalidUnicodeCodepoint);
            if (delimiter != '\'' && delimiter != '"')
                throw new ArgumentException(SR.DelimiterMustBeSingleOrDoubleQuote, nameof(delimiter));
            switch (c)
            {
                case '\0': return "\\0";
                case '\a': return "\\a";
                case '\b': return "\\b";
                case '\t': return "\\t";
                case '\n': return "\\n";
                case '\v': return "\\v";
                case '\f': return "\\f";
                case '\r': return "\\r";
                case '\\': return "\\\\";
                case '\'': return delimiter == '\'' ? "\\'" : "'";
                case '"': return delimiter == '"' ? "\\\"" : "\"";
                default:
                    if (' ' <= c && c <= 0x7E)
                        return "" + (char)c;
                    else if (0 <= c && c <= 0xFFFF)
                        return string.Format("\\u{0:X4}", c);
                    else
                        return string.Format("\\U{0:X8}", c);
            }
        }

        public virtual string FormatIdentifier(Identifier n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            string name = n.Name;
            if (name.Length == 0)
                throw new ArgumentException(SR.InvalidEmptyIdentifier, nameof(n));
            if (IsKeyword(name))
                return EscapeKeyword(name);
            if (IsSimpleIdentifier(name))
                return name;
            return EscapeIdentifier(name);
        }

        public virtual string FormatBooleanLiteral(BooleanLiteral n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return n.Value ? "true" : "false";
        }

        public virtual string FormatIntegerLiteral(IntegerLiteral n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            bool isHex = n.IsHexadecimal ?? false;
            BigInteger v = n.Value;
            StringBuilder sb = new StringBuilder();
            if (v < 0)
            {
                sb.Append("-");
                v = -v;
            }
            if (isHex)
            {
                string str = v.ToString("X", CultureInfo.InvariantCulture);
                str = str.TrimStart('0');
                if (str.Length == 0)
                    str = "0";
                sb.Append("0x");
                sb.Append(str);
            }
            else
            {
                string str = v.ToString(CultureInfo.InvariantCulture);
                sb.Append(str);
            }
            if (n.Suffix != null)
                sb.Append(n.Suffix.Value.ToString());
            return sb.ToString();
        }

        public virtual string FormatFloatLiteral(FloatLiteral n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (float.IsNaN(n.Value))
                return "(1e39f / 1e39f)";
            else if (float.IsPositiveInfinity(n.Value))
                return "1e39f";
            else if (float.IsNegativeInfinity(n.Value))
                return "(-1e39f)";
            else
            {
                string str = n.Value.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
                str = str.Replace("e+", "e");
                if (n.Suffix != null)
                    str += n.Suffix.ToString();
                else
                    str += "f";
                return str;
            }
        }

        public virtual string FormatDoubleLiteral(DoubleLiteral n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (double.IsNaN(n.Value))
                return "(1e309 / 1e309)";
            else if (double.IsPositiveInfinity(n.Value))
                return "1e309";
            else if (double.IsNegativeInfinity(n.Value))
                return "(-1e309)";
            else
            {
                string str = n.Value.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
                str = str.Replace("e+", "e");
                if (str.IndexOfAny(new[] { '.', 'e' }) == -1)
                    str += ".0";
                if (n.Suffix != null)
                    str += n.Suffix.ToString();
                return str;
            }
        }

        public virtual string FormatDecimalLiteral(DecimalLiteral n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            string str = n.Value.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
            str = str.Replace("e+", "e");
            if (n.Suffix != null)
                str += n.Suffix.ToString();
            else
                str += "m";
            return str;
        }

        public virtual string FormatCharacterLiteral(CharacterLiteral n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            const char delimiter = '\'';
            string str = EscapeCharacter(n.Value, delimiter);
            StringBuilder sb = new StringBuilder();
            sb.Append(delimiter);
            sb.Append(str);
            sb.Append(delimiter);
            return sb.ToString();
        }

        public virtual string FormatStringLiteral(StringLiteral n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            const char delimiter = '"';
            StringBuilder sb = new StringBuilder();
            bool isVerbatim = n.IsVerbatim ?? false;
            if (isVerbatim)
            {
                sb.Append("@");
                sb.Append(delimiter);
                foreach (char c in n.Value)
                {
                    if (c == '"')
                        sb.Append('"');
                    sb.Append(c);
                }
                sb.Append(delimiter);
            }
            else
            {
                sb.Append(delimiter);
                foreach (int c in n.Value.EnumCodepoints())
                {
                    string str = EscapeCharacter(c, delimiter);
                    sb.Append(str);
                }
                sb.Append(delimiter);
            }
            return sb.ToString();
        }

        public virtual string FormatNullLiteral(NullLiteral n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return "null";
        }

        public virtual void WriteIdentifier(Identifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            string str = FormatIdentifier(n);
            writer.Write(str);
        }

        public virtual void WriteBooleanLiteral(BooleanLiteral n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            string str = FormatBooleanLiteral(n);
            writer.Write(str);
        }

        public virtual void WriteIntegerLiteral(IntegerLiteral n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            string str = FormatIntegerLiteral(n);
            writer.Write(str);
        }

        public virtual void WriteFloatLiteral(FloatLiteral n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            string str = FormatFloatLiteral(n);
            writer.Write(str);
        }

        public virtual void WriteDoubleLiteral(DoubleLiteral n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            string str = FormatDoubleLiteral(n);
            writer.Write(str);
        }

        public virtual void WriteDecimalLiteral(DecimalLiteral n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            string str = FormatDecimalLiteral(n);
            writer.Write(str);
        }

        public virtual void WriteCharacterLiteral(CharacterLiteral n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            string str = FormatCharacterLiteral(n);
            writer.Write(str);
        }

        public virtual void WriteStringLiteral(StringLiteral n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            string str = FormatStringLiteral(n);
            writer.Write(str);
        }

        public virtual void WriteNullLiteral(NullLiteral n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            string str = FormatNullLiteral(n);
            writer.Write(str);
        }
        #endregion

        #region P492 B.2.1 Basic concepts
        public virtual void WriteNamespaceName(NamespaceName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteNamespaceOrTypeName(n.Name, writer);
        }

        public virtual void WriteTypeName(TypeName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteNamespaceOrTypeName(n.Name, writer);
        }

        public virtual void WriteUnqualifiedNamespaceOrTypeName(UnqualifiedNamespaceOrTypeName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            if (n.TypeArguments != null)
                WriteTypeArgumentList(n.TypeArguments, writer);
        }

        public virtual void WriteQualifiedNamespaceOrTypeName(QualifiedNamespaceOrTypeName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteNamespaceOrTypeName(n.Operand, writer);
            writer.Write(".");
            WriteIdentifier(n.Name, writer);
            if (n.TypeArguments != null)
                WriteTypeArgumentList(n.TypeArguments, writer);
        }

        public virtual void WriteQualifiedAliasMemberNamespaceOrTypeName(QualifiedAliasMemberNamespaceOrTypeName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteQualifiedAliasMember(n.Member, writer);
        }
        #endregion

        #region P492 B.2.2 Types
        public virtual void WriteNamedStructType(NamedStructType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeName(n.Name, writer);
        }

        public virtual void WriteSByteType(SByteType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("sbyte");
        }

        public virtual void WriteByteType(ByteType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("byte");
        }

        public virtual void WriteShortType(ShortType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("short");
        }

        public virtual void WriteUShortType(UShortType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("ushort");
        }

        public virtual void WriteIntType(IntType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("int");
        }

        public virtual void WriteUIntType(UIntType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("uint");
        }

        public virtual void WriteLongType(LongType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("long");
        }

        public virtual void WriteULongType(ULongType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("ulong");
        }

        public virtual void WriteCharType(CharType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("char");
        }

        public virtual void WriteFloatType(FloatType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("float");
        }

        public virtual void WriteDoubleType(DoubleType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("double");
        }

        public virtual void WriteDecimalType(DecimalType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("decimal");
        }

        public virtual void WriteBoolType(BoolType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("bool");
        }

        public virtual void WriteNullableType(NullableType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteNonNullableValueType(n.Operand, writer);
            writer.Write("?");
        }

        public virtual void WriteEnumType(EnumType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeName(n.Name, writer);
        }

        public virtual void WriteNamedClassType(NamedClassType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeName(n.Name, writer);
        }

        public virtual void WriteObjectType(ObjectType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("object");
        }

        public virtual void WriteDynamicType(DynamicType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("dynamic");
        }

        public virtual void WriteStringType(StringType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("string");
        }

        public virtual void WriteInterfaceType(InterfaceType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeName(n.Name, writer);
        }

        public virtual void WriteArrayType(ArrayType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteNonArrayType(n.ElementType, writer);
            WriteRankSpecifiers(n.Rank, writer);
        }

        public virtual void WriteDelegateType(DelegateType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeName(n.Name, writer);
        }

        public virtual void WriteTypeParameterType(TypeParameterType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
        }

        public virtual void WriteNonNullableValueType(NonNullableValueType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteType(n.Type, writer);
        }

        public virtual void WriteNonArrayType(NonArrayType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteType(n.Type, writer);
        }

        public virtual void WriteTypeArgumentList(TypeArgumentList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("<");
            WriteTypeArguments(n.Arguments, writer);
            writer.Write(">");
        }

        public virtual void WriteTypeArguments(TypeArguments n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteTypeArgument(n.Items[i], writer);
            }
        }

        public virtual void WriteTypeArgument(TypeArgument n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteType(n.Type, writer);
        }
        #endregion

        #region P494 B.2.3 Variables
        public virtual void WriteVariableReference(VariableReference n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Variable, writer);
        }
        #endregion

        #region P494 B.2.4 Expressions
        protected const int PrimaryExpressionOpPrecedence = 15;
        protected const int UnaryExpressionOpPrecedence = 14;
        protected const int MultiplicativeExpressionOpPrecedence = 13;
        protected const int AdditiveExpressionOpPrecedence = 12;
        protected const int ShiftExpressionOpPrecedence = 11;
        protected const int RelationalExpressionOpPrecedence = 10;
        protected const int EqualityExpressionOpPrecedence = 9;
        protected const int BitwiseAndExpressionOpPrecedence = 8;
        protected const int BitwiseXorExpressionOpPrecedence = 7;
        protected const int BitwiseOrExpressionOpPrecedence = 6;
        protected const int LogicalAndExpressionOpPrecedence = 5;
        protected const int LogicalOrExpressionOpPrecedence = 4;
        protected const int NullCoalescingExpressionOpPrecedence = 3;
        protected const int ConditionalExpressionOpPrecedence = 2;
        protected const int NonAssignmentExpressionOpPrecedence = 1;
        protected const int AssignmentExpressionOpPrecedence = 0;

        public virtual void WriteArgumentList(ArgumentList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteArgument(n.Items[i], writer);
            }
        }

        public virtual void WriteArgument(Argument n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Name != null)
            {
                WriteArgumentName(n.Name, writer);
                writer.Write(" ");
            }
            WriteArgumentValue(n.Value, writer);
        }

        public virtual void WriteArgumentName(ArgumentName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            writer.Write(":");
        }

        public virtual void WriteInArgumentValue(InArgumentValue n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer);
        }

        public virtual void WriteRefArgumentValue(RefArgumentValue n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("ref ");
            WriteVariableReference(n.Value, writer);
        }

        public virtual void WriteOutArgumentValue(OutArgumentValue n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("out ");
            WriteVariableReference(n.Value, writer);
        }

        public virtual void WriteLiteralExpression(LiteralExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteLiteral(n.Value, writer);
        }

        public virtual void WriteSimpleNameExpression(SimpleNameExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSimpleName(n.Name, writer);
        }

        public virtual void WriteParenthesizedExpression(ParenthesizedExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("(");
            WriteExpression(n.Operand, writer);
            writer.Write(")");
        }

        public virtual void WriteBlockCommentExpression(BlockCommentExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("/* ");
            writer.Write(n.Content);
            writer.Write(" */");
        }

        public virtual void WriteObjectMemberAccessExpression(ObjectMemberAccessExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Operand, writer, prec);
            writer.Write(".");
            WriteIdentifier(n.Member, writer);
            if (n.TypeArguments != null)
                WriteTypeArgumentList(n.TypeArguments, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteNullableObjectMemberAccessExpression(NullableObjectMemberAccessExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Operand, writer, prec);
            writer.Write("?.");
            WriteIdentifier(n.Member, writer);
            if (n.TypeArguments != null)
                WriteTypeArgumentList(n.TypeArguments, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WritePredefinedTypeMemberAccessExpression(PredefinedTypeMemberAccessExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WritePredefinedType(n.Operand, writer);
            writer.Write(".");
            WriteIdentifier(n.Member, writer);
            if (n.TypeArguments != null)
                WriteTypeArgumentList(n.TypeArguments, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteQualifiedAliasMemberAccessExpression(QualifiedAliasMemberAccessExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteQualifiedAliasMember(n.Operand, writer);
            writer.Write(".");
            WriteIdentifier(n.Member, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteInvocationExpression(InvocationExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Operand, writer, prec);
            writer.Write("(");
            if (n.Arguments != null)
                WriteArgumentList(n.Arguments, writer);
            writer.Write(")");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteElementAccessExpression(ElementAccessExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WritePrimaryNoArrayCreationExpression(n.Operand, writer);
            writer.Write("[");
            WriteExpressionList(n.Arguments, writer);
            writer.Write("]");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteThisAccessExpression(ThisAccessExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("this");
        }

        public virtual void WriteBaseMemberAccessExpression(BaseMemberAccessExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("base");
            writer.Write(".");
            WriteIdentifier(n.Member, writer);
        }

        public virtual void WriteBaseElementAccessExpression(BaseElementAccessExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("base");
            writer.Write("[");
            WriteExpressionList(n.Arguments, writer);
            writer.Write("]");
        }

        public virtual void WritePostIncrementExpression(PostIncrementExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Operand, writer, prec);
            string str = n.Operand.ToString(this);
            if (str.EndsWith("+"))
                writer.Write(" ");
            writer.Write("++");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WritePostDecrementExpression(PostDecrementExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Operand, writer, prec);
            string str = n.Operand.ToString(this);
            if (str.EndsWith("-"))
                writer.Write(" ");
            writer.Write("--");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteObjectCreationExpression(ObjectCreationExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("new ");
            WriteType(n.Type, writer);
            writer.Write("(");
            if (n.Arguments != null)
                WriteArgumentList(n.Arguments, writer);
            writer.Write(")");
            if (n.Initializer != null)
            {
                writer.Write(" ");
                WriteObjectOrCollectionInitializer(n.Initializer, writer);
            }
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteObjectCreateionWithInitializerExpression(ObjectCreateionWithInitializerExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("new ");
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteObjectOrCollectionInitializer(n.Initializer, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteDelegateCreationExpression(DelegateCreationExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("new ");
            WriteDelegateType(n.Type, writer);
            writer.Write("(");
            WriteExpression(n.Argument, writer);
            writer.Write(")");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteAnonymousObjectCreationExpression(AnonymousObjectCreationExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("new ");
            WriteAnonymousObjectInitializer(n.Initializer, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteValueTupleCreationExpression(ValueTupleCreationExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("(");
            WriteExpressionList(n.Arguments, writer);
            writer.Write(")");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteTypeofExpression(TypeofExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("typeof(");
            WriteType(n.Type, writer);
            writer.Write(")");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteUnboundTypeofExpression(UnboundTypeofExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("typeof(");
            WriteUnboundTypeName(n.Type, writer);
            writer.Write(")");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteVoidTypeofExpression(VoidTypeofExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("typeof(void)");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteCheckedExpression(CheckedExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("checked(");
            WriteExpression(n.Operand, writer);
            writer.Write(")");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteUncheckedExpression(UncheckedExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("unchecked(");
            WriteExpression(n.Operand, writer);
            writer.Write(")");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteDefaultValueExpression(DefaultValueExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("default(");
            WriteType(n.Type, writer);
            writer.Write(")");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteNameofExpression(NameofExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("nameof(");
            WriteNamedEntity(n.Entity, writer);
            writer.Write(")");
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteAnonymousMethodExpression(AnonymousMethodExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("delegate");
            if (n.Signature != null)
                WriteExplicitAnonymousFunctionSignature(n.Signature, writer);
            writer.Write("\n");
            WriteBlock(n.Body, writer, true);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteArrayCreationWithDimensionsExpression(ArrayCreationWithDimensionsExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("new ");
            WriteNonArrayType(n.ElementType, writer);
            writer.Write("[");
            WriteExpressionList(n.Dimensions, writer);
            writer.Write("]");
            if (n.Specifiers != null)
                WriteRankSpecifiers(n.Specifiers, writer);
            if (n.Initializer != null)
            {
                writer.Write(" ");
                WriteArrayInitializer(n.Initializer, writer);
            }
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteArrayCreationWithArrayTypeExpression(ArrayCreationWithArrayTypeExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("new ");
            WriteArrayType(n.ArrayType, writer);
            writer.Write(" ");
            WriteArrayInitializer(n.Initializer, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteArrayCreationWithRankSpecifierExpression(ArrayCreationWithRankSpecifierExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = PrimaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("new");
            WriteRankSpecifier(n.Specifier, writer);
            writer.Write(" ");
            WriteArrayInitializer(n.Initializer, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WritePositiveExpression(PositiveExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = UnaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("+");
            string str = n.Operand.ToString(this);
            if (str.StartsWith("+"))
                writer.Write(" ");
            WriteExpression(n.Operand, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteNegativeExpression(NegativeExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = UnaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("-");
            string str = n.Operand.ToString(this);
            if (str.StartsWith("-"))
                writer.Write(" ");
            WriteExpression(n.Operand, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteLogicalNotExpression(LogicalNotExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = UnaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("!");
            WriteExpression(n.Operand, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteBitwiseNotExpression(BitwiseNotExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = UnaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("~");
            WriteExpression(n.Operand, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WritePreIncrementExpression(PreIncrementExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = UnaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("++");
            string str = n.Operand.ToString(this);
            if (str.StartsWith("+"))
                writer.Write(" ");
            WriteExpression(n.Operand, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WritePreDecrementExpression(PreDecrementExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = UnaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("--");
            string str = n.Operand.ToString(this);
            if (str.StartsWith("-"))
                writer.Write(" ");
            WriteExpression(n.Operand, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteCastExpression(CastExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = UnaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("(");
            WriteType(n.Type, writer);
            writer.Write(")");
            WriteExpression(n.Operand, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteAwaitExpression(AwaitExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = UnaryExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            writer.Write("await ");
            WriteExpression(n.Operand, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteMultiplyExpression(MultiplyExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = MultiplicativeExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" * ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteDivideExpression(DivideExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = MultiplicativeExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" / ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteModuloExpression(ModuloExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = MultiplicativeExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" % ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteAddExpression(AddExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = AdditiveExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" + ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteSubtractExpression(SubtractExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = AdditiveExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" - ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteLeftShiftExpression(LeftShiftExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = ShiftExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" << ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteRightShiftExpression(RightShiftExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = ShiftExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" >> ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteLessThanExpression(LessThanExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = RelationalExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" < ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteGreaterThanExpression(GreaterThanExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = RelationalExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" > ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteLessEqualExpression(LessEqualExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = RelationalExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" <= ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteGreaterEqualExpression(GreaterEqualExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = RelationalExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" >= ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteIsInstanceOfExpression(IsInstanceOfExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = RelationalExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Operand, writer, prec);
            writer.Write(" is ");
            WriteType(n.Type, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteAsInstanceOfExpression(AsInstanceOfExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = RelationalExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Operand, writer, prec);
            writer.Write(" as ");
            WriteType(n.Type, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteEqualToExpression(EqualToExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = EqualityExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" == ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteNotEqualToExpression(NotEqualToExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = EqualityExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" != ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteBitwiseAndExpression(BitwiseAndExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = BitwiseAndExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" & ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteBitwiseXorExpression(BitwiseXorExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = BitwiseXorExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" ^ ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteBitwiseOrExpression(BitwiseOrExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = BitwiseOrExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" | ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteLogicalAndExpression(LogicalAndExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = LogicalAndExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" && ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteLogicalOrExpression(LogicalOrExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = LogicalOrExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec);
            writer.Write(" || ");
            WriteExpression(n.Right, writer, prec + 1);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteNullCoalescingExpression(NullCoalescingExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = NullCoalescingExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Left, writer, prec + 1);
            writer.Write(" ?? ");
            WriteExpression(n.Right, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteConditionalExpression(ConditionalExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = ConditionalExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteExpression(n.Condition, writer, prec + 1);
            writer.Write(" ? ");
            WriteExpression(n.TruePart, writer, prec);
            writer.Write(" : ");
            WriteExpression(n.FalsePart, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteLambdaExpression(LambdaExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = NonAssignmentExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteAnonymousFunctionSignature(n.Signature, writer);
            writer.Write(" =>");
            WriteAnonymousFunctionBody(n.Body, writer);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteQueryExpression(QueryExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = NonAssignmentExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            using (writer.ColumnAlignment)
            {
                WriteFromClause(n.FromClause, writer);
                writer.Write("\n");
                WriteQueryBody(n.QueryBody, writer);
            }
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteAssignmentExpression(AssignmentExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            const int prec = AssignmentExpressionOpPrecedence;
            if (d > prec)
                writer.Write("(");
            WriteUnaryExpression(n.Left, writer, UnaryExpressionOpPrecedence);
            writer.Write(" ");
            WriteAssignmentOperator(n.Operator, writer);
            writer.Write(" ");
            WriteExpression(n.Right, writer, prec);
            if (d > prec)
                writer.Write(")");
        }

        public virtual void WriteSimpleName(SimpleName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            if (n.TypeArguments != null)
                WriteTypeArgumentList(n.TypeArguments, writer);
        }

        public virtual void WriteSBytePredefinedType(SBytePredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("sbyte");
        }

        public virtual void WriteBytePredefinedType(BytePredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("byte");
        }

        public virtual void WriteShortPredefinedType(ShortPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("short");
        }

        public virtual void WriteUShortPredefinedType(UShortPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("ushort");
        }

        public virtual void WriteIntPredefinedType(IntPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("int");
        }

        public virtual void WriteUIntPredefinedType(UIntPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("uint");
        }

        public virtual void WriteLongPredefinedType(LongPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("long");
        }

        public virtual void WriteULongPredefinedType(ULongPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("ulong");
        }

        public virtual void WriteCharPredefinedType(CharPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("char");
        }

        public virtual void WriteFloatPredefinedType(FloatPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("float");
        }

        public virtual void WriteDoublePredefinedType(DoublePredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("double");
        }

        public virtual void WriteDecimalPredefinedType(DecimalPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("decimal");
        }

        public virtual void WriteBoolPredefinedType(BoolPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("bool");
        }

        public virtual void WriteObjectPredefinedType(ObjectPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("object");
        }

        public virtual void WriteStringPredefinedType(StringPredefinedType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("string");
        }

        public virtual void WriteObjectObjectOrCollectionInitializer(ObjectObjectOrCollectionInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteObjectInitializer(n.Value, writer);
        }

        public virtual void WriteCollectionObjectOrCollectionInitializer(CollectionObjectOrCollectionInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteCollectionInitializer(n.Value, writer);
        }

        public virtual void WriteObjectInitializer(ObjectInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("{");
            writer.Write(" ");
            if (n.MemberInitializers != null)
            {
                WriteMemberInitializerList(n.MemberInitializers, writer);
                if (n.HasTrailingComma ?? false)
                    writer.Write(",");
                writer.Write(" ");
            }
            writer.Write("}");
        }

        public virtual void WriteMemberInitializerList(MemberInitializerList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteMemberInitializer(n.Items[i], writer);
            }
        }

        public virtual void WriteMemberInitializer(MemberInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            writer.Write(" = ");
            WriteInitializerValue(n.Value, writer);
        }

        public virtual void WriteMemberInitializerValue(MemberInitializerValue n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer);
        }

        public virtual void WriteObjectOrCollectionInitializerValue(ObjectOrCollectionInitializerValue n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteObjectOrCollectionInitializer(n.Value, writer);
        }

        public virtual void WriteCollectionInitializer(CollectionInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("{");
            writer.Write(" ");
            WriteElementInitializerList(n.ElementInitializers, writer);
            if (n.HasTrailingComma ?? false)
                writer.Write(",");
            writer.Write(" ");
            writer.Write("}");
        }

        public virtual void WriteElementInitializerList(ElementInitializerList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteElementInitializer(n.Items[i], writer);
            }
        }

        public virtual void WriteSingleElementInitializer(SingleElementInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer, NonAssignmentExpressionOpPrecedence);
        }

        public virtual void WriteMultipleElementInitializer(MultipleElementInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("{");
            writer.Write(" ");
            WriteExpressionList(n.Values, writer);
            writer.Write(" ");
            writer.Write("}");
        }

        public virtual void WriteExpressionList(ExpressionList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteExpression(n.Items[i], writer);
            }
        }

        public virtual void WriteAnonymousObjectInitializer(AnonymousObjectInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("{");
            writer.Write(" ");
            if (n.MemberDeclarators != null)
            {
                WriteMemberDeclaratorList(n.MemberDeclarators, writer);
                if (n.HasTrailingComma ?? false)
                    writer.Write(",");
                writer.Write(" ");
            }
            writer.Write("}");
        }

        public virtual void WriteMemberDeclaratorList(MemberDeclaratorList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteMemberDeclarator(n.Items[i], writer);
            }
        }

        public virtual void WriteSimpleNameMemberDeclarator(SimpleNameMemberDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSimpleName(n.Name, writer);
        }

        public virtual void WriteMemberAccessMemberDeclarator(MemberAccessMemberDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteMemberAccessExpression(n.Member, writer, PrimaryExpressionOpPrecedence);
        }

        public virtual void WriteBindingMemberDeclarator(BindingMemberDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            writer.Write(" = ");
            WriteExpression(n.Value, writer);
        }

        public virtual void WriteUnqualifiedUnboundTypeName(UnqualifiedUnboundTypeName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            if (n.Dimension != null)
                WriteGenericDimensionSpecifier(n.Dimension, writer);
        }

        public virtual void WriteQualifiedUnboundTypeName(QualifiedUnboundTypeName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteUnboundTypeName(n.Operand, writer);
            writer.Write(".");
            WriteIdentifier(n.Name, writer);
            if (n.Dimension != null)
                WriteGenericDimensionSpecifier(n.Dimension, writer);
        }

        public virtual void WriteQualifiedAliasMemberUnboundTypeName(QualifiedAliasMemberUnboundTypeName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteUnboundQualifiedAliasMember(n.Member, writer);
        }

        public virtual void WriteUnboundQualifiedAliasMember(UnboundQualifiedAliasMember n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Scope, writer);
            writer.Write("::");
            WriteIdentifier(n.Member, writer);
            if (n.Dimension != null)
                WriteGenericDimensionSpecifier(n.Dimension, writer);
        }

        public virtual void WriteGenericDimensionSpecifier(GenericDimensionSpecifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("<");
            for (int i = 1; i < n.Dimension; i++)
                writer.Write(",");
            writer.Write(">");
        }

        public virtual void WriteSimpleNamedEntity(SimpleNamedEntity n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSimpleName(n.Name, writer);
        }

        public virtual void WriteQualifiedNamedEntity(QualifiedNamedEntity n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteNamedEntityTarget(n.Target, writer);
            writer.Write(".");
            WriteIdentifier(n.Member, writer);
            if (n.TypeArguments != null)
                WriteTypeArgumentList(n.TypeArguments, writer);
        }

        public virtual void WriteThisNamedEntityTarget(ThisNamedEntityTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("this");
        }

        public virtual void WriteBaseNamedEntityTarget(BaseNamedEntityTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("base");
        }

        public virtual void WriteNamedEntityNamedEntityTarget(NamedEntityNamedEntityTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteNamedEntity(n.Entity, writer);
        }

        public virtual void WritePredefinedTypeNamedEntityTarget(PredefinedTypeNamedEntityTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WritePredefinedType(n.Type, writer);
        }

        public virtual void WriteQualifiedAliasMemberNamedEntityTarget(QualifiedAliasMemberNamedEntityTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteQualifiedAliasMember(n.Member, writer);
        }

        public virtual void WriteExplicitAnonymousFunctionSignature(ExplicitAnonymousFunctionSignature n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("(");
            if (n.Parameters != null)
                WriteExplicitAnonymousFunctionParameterList(n.Parameters, writer);
            writer.Write(")");
        }

        public virtual void WriteFullImplicitAnonymousFunctionSignature(FullImplicitAnonymousFunctionSignature n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("(");
            if (n.Parameters != null)
                WriteImplicitAnonymousFunctionParameterList(n.Parameters, writer);
            writer.Write(")");
        }

        public virtual void WriteSimpleImplicitAnonymousFunctionSignature(SimpleImplicitAnonymousFunctionSignature n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteImplicitAnonymousFunctionParameter(n.Parameter, writer);
        }

        public virtual void WriteExplicitAnonymousFunctionParameterList(ExplicitAnonymousFunctionParameterList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteExplicitAnonymousFunctionParameter(n.Items[i], writer);
            }
        }

        public virtual void WriteExplicitAnonymousFunctionParameter(ExplicitAnonymousFunctionParameter n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Modifier != null)
            {
                WriteExplicitAnonymousFunctionParameterModifier(n.Modifier, writer);
                writer.Write(" ");
            }
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteIdentifier(n.Name, writer);
        }

        public virtual void WriteRefExplicitAnonymousFunctionParameterModifier(RefExplicitAnonymousFunctionParameterModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("ref");
        }

        public virtual void WriteOutExplicitAnonymousFunctionParameterModifier(OutExplicitAnonymousFunctionParameterModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("out");
        }

        public virtual void WriteImplicitAnonymousFunctionParameterList(ImplicitAnonymousFunctionParameterList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteImplicitAnonymousFunctionParameter(n.Items[i], writer);
            }
        }

        public virtual void WriteImplicitAnonymousFunctionParameter(ImplicitAnonymousFunctionParameter n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
        }

        public virtual void WriteExpressionAnonymousFunctionBody(ExpressionAnonymousFunctionBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(" ");
            WriteExpression(n.Expression, writer);
        }

        public virtual void WriteBlockAnonymousFunctionBody(BlockAnonymousFunctionBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("\n");
            WriteBlock(n.Block, writer);
        }

        public virtual void WriteFromClause(FromClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("from ");
            if (n.Type != null)
            {
                WriteType(n.Type, writer);
                writer.Write(" ");
            }
            WriteIdentifier(n.Enumerator, writer);
            writer.Write(" in ");
            WriteExpression(n.Enumerable, writer);
        }

        public virtual void WriteQueryBody(QueryBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Clauses != null)
            {
                WriteQueryBodyClauses(n.Clauses, writer);
                writer.Write("\n");
            }
            WriteSelectOrGroupClause(n.SelectOrGroup, writer);
            if (n.Continuation != null)
            {
                writer.Write(" ");
                WriteQueryContinuation(n.Continuation, writer);
            }
        }

        public virtual void WriteQueryBodyClauses(QueryBodyClauses n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write("\n");
                WriteQueryBodyClause(n.Items[i], writer);
            }
        }

        public virtual void WriteFromQueryBodyClause(FromQueryBodyClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteFromClause(n.Clause, writer);
        }

        public virtual void WriteLetQueryBodyClause(LetQueryBodyClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteLetClause(n.Clause, writer);
        }

        public virtual void WriteWhereQueryBodyClause(WhereQueryBodyClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteWhereClause(n.Clause, writer);
        }

        public virtual void WriteJoinQueryBodyClause(JoinQueryBodyClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteJoinClause(n.Clause, writer);
        }

        public virtual void WriteJoinIntoQueryBodyClause(JoinIntoQueryBodyClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteJoinIntoClause(n.Clause, writer);
        }

        public virtual void WriteOrderbyQueryBodyClause(OrderbyQueryBodyClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteOrderbyClause(n.Clause, writer);
        }

        public virtual void WriteLetClause(LetClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("let ");
            WriteIdentifier(n.Name, writer);
            writer.Write(" = ");
            WriteExpression(n.Value, writer);
        }

        public virtual void WriteWhereClause(WhereClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("where ");
            WriteBooleanExpression(n.Condition, writer);
        }

        public virtual void WriteJoinClause(JoinClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("join ");
            if (n.Type != null)
            {
                WriteType(n.Type, writer);
                writer.Write(" ");
            }
            WriteIdentifier(n.Name, writer);
            writer.Write(" in ");
            WriteExpression(n.InOperand, writer);
            writer.Write(" on ");
            WriteExpression(n.OnOperand, writer);
            writer.Write(" equals ");
            WriteExpression(n.EqualsOperand, writer);
        }

        public virtual void WriteJoinIntoClause(JoinIntoClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("join ");
            if (n.Type != null)
            {
                WriteType(n.Type, writer);
                writer.Write(" ");
            }
            WriteIdentifier(n.Name, writer);
            writer.Write(" in ");
            WriteExpression(n.InOperand, writer);
            writer.Write(" on ");
            WriteExpression(n.OnOperand, writer);
            writer.Write(" equals ");
            WriteExpression(n.EqualsOperand, writer);
            writer.Write(" into ");
            WriteIdentifier(n.Target, writer);
        }

        public virtual void WriteOrderbyClause(OrderbyClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("orderby ");
            WriteOrderings(n.Orderings, writer);
        }

        public virtual void WriteOrderings(Orderings n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteOrdering(n.Items[i], writer);
            }
        }

        public virtual void WriteOrdering(Ordering n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer);
            if (n.Direction != null)
            {
                writer.Write(" ");
                WriteOrderingDirection(n.Direction, writer);
            }
        }

        public virtual void WriteAscendingOrderingDirection(AscendingOrderingDirection n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("ascending");
        }

        public virtual void WriteDescendingOrderingDirection(DescendingOrderingDirection n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("descending");
        }

        public virtual void WriteSelectSelectOrGroupClause(SelectSelectOrGroupClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSelectClause(n.Clause, writer);
        }

        public virtual void WriteGroupSelectOrGroupClause(GroupSelectOrGroupClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteGroupClause(n.Clause, writer);
        }

        public virtual void WriteSelectClause(SelectClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("select ");
            WriteExpression(n.Value, writer);
        }

        public virtual void WriteGroupClause(GroupClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("group ");
            WriteExpression(n.Value, writer);
            writer.Write(" by ");
            WriteExpression(n.Key, writer);
        }

        public virtual void WriteQueryContinuation(QueryContinuation n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("into ");
            WriteIdentifier(n.Target, writer);
            writer.Write("\n");
            WriteQueryBody(n.QueryBody, writer);
        }

        public virtual void WriteAssignAssignmentOperator(AssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("=");
        }

        public virtual void WriteMultiplyAssignAssignmentOperator(MultiplyAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("*=");
        }

        public virtual void WriteDivideAssignAssignmentOperator(DivideAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("/=");
        }

        public virtual void WriteModuloAssignAssignmentOperator(ModuloAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("%=");
        }

        public virtual void WriteAddAssignAssignmentOperator(AddAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("+=");
        }

        public virtual void WriteSubtractAssignAssignmentOperator(SubtractAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("-=");
        }

        public virtual void WriteLeftShiftAssignAssignmentOperator(LeftShiftAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("<<=");
        }

        public virtual void WriteRightShiftAssignAssignmentOperator(RightShiftAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(">>=");
        }

        public virtual void WriteBitwiseAndAssignAssignmentOperator(BitwiseAndAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("&=");
        }

        public virtual void WriteBitwiseXorAssignAssignmentOperator(BitwiseXorAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("^=");
        }

        public virtual void WriteBitwiseOrAssignAssignmentOperator(BitwiseOrAssignAssignmentOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("|=");
        }

        public virtual void WriteConstantExpression(ConstantExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer, d);
        }

        public virtual void WriteBooleanExpression(BooleanExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer, d);
        }
        #endregion

        #region P501 B.2.5 Statements
        public virtual void WriteLabeledStatement(LabeledStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.CloseBlock();
            WriteIdentifier(n.Label, writer);
            writer.Write(":\n");
            writer.OpenBlock();
            WriteStatement(n.Operand, writer);
        }

        public virtual void WriteLocalVariableDeclarationStatement(LocalVariableDeclarationStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteLocalVariableDeclaration(n.Declaration, writer);
            writer.Write(";\n");
        }

        public virtual void WriteLocalConstantDeclarationStatement(LocalConstantDeclarationStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteLocalConstantDeclaration(n.Declaration, writer);
            writer.Write(";\n");
        }

        public virtual void WriteBlockStatement(BlockStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteBlock(n.Block, writer);
        }

        public virtual void WriteEmptyStatement(EmptyStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(";\n");
        }

        public virtual void WriteLineCommentStatement(LineCommentStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("// {0}\n", n.Content);
        }

        public virtual void WriteExpressionStatement(ExpressionStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteStatementExpression(n.Expression, writer);
            writer.Write(";\n");
        }

        public virtual void WriteIfStatement(IfStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("if (");
            WriteBooleanExpression(n.Condition, writer);
            writer.Write(")\n");
            WriteCompoundStatementBody(n.Body, writer);
            if (n.OrElse != null)
            {
                writer.Write("else\n");
                WriteCompoundStatementBody(n.OrElse, writer);
            }
        }

        public virtual void WriteSwitchStatement(SwitchStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("switch (");
            WriteExpression(n.Value, writer);
            writer.Write(")\n");
            WriteSwitchBlock(n.Body, writer);
        }

        public virtual void WriteWhileStatement(WhileStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("while (");
            WriteBooleanExpression(n.Condition, writer);
            writer.Write(")\n");
            WriteCompoundStatementBody(n.Body, writer);
        }

        public virtual void WriteDoStatement(DoStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("do\n");
            WriteCompoundStatementBody(n.Body, writer);
            writer.Write("while (");
            WriteBooleanExpression(n.Condition, writer);
            writer.Write(");\n");
        }

        public virtual void WriteForStatement(ForStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("for (");
            if (n.Initializer != null)
                WriteForInitializer(n.Initializer, writer);
            writer.Write(";");
            if (n.Initializer != null || n.Condition != null || n.Iterator != null)
                writer.Write(" ");
            if (n.Condition != null)
                WriteForCondition(n.Condition, writer);
            writer.Write(";");
            if (n.Iterator != null)
            {
                writer.Write(" ");
                WriteForIterator(n.Iterator, writer);
            }
            writer.Write(")\n");
            WriteCompoundStatementBody(n.Body, writer);
        }

        public virtual void WriteForEachStatement(ForEachStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("foreach (");
            WriteLocalVariableType(n.Type, writer);
            writer.Write(" ");
            WriteIdentifier(n.Enumerator, writer);
            writer.Write(" in ");
            WriteExpression(n.Enumerable, writer);
            writer.Write(")\n");
            WriteCompoundStatementBody(n.Body, writer);
        }

        public virtual void WriteBreakStatement(BreakStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("break;\n");
        }

        public virtual void WriteContinueStatement(ContinueStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("continue;\n");
        }

        public virtual void WriteGotoLabelStatement(GotoLabelStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("goto ");
            WriteIdentifier(n.Label, writer);
            writer.Write(";\n");
        }

        public virtual void WriteGotoCaseStatement(GotoCaseStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("goto case ");
            WriteConstantExpression(n.Value, writer);
            writer.Write(";\n");
        }

        public virtual void WriteGotoDefaultStatement(GotoDefaultStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("goto default;\n");
        }

        public virtual void WriteReturnStatement(ReturnStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("return");
            if (n.Value != null)
            {
                writer.Write(" ");
                WriteExpression(n.Value, writer);
            }
            writer.Write(";\n");
        }

        public virtual void WriteThrowStatement(ThrowStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("throw");
            if (n.Value != null)
            {
                writer.Write(" ");
                WriteExpression(n.Value, writer);
            }
            writer.Write(";\n");
        }

        public virtual void WriteTryStatement(TryStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("try\n");
            WriteBlock(n.Body, writer);
            WriteCatchClauseList(n.Clauses, writer);
        }

        public virtual void WriteTryWithFinallyStatement(TryWithFinallyStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("try\n");
            WriteBlock(n.Body, writer);
            if (n.Clauses != null)
                WriteCatchClauseList(n.Clauses, writer);
            WriteFinallyClause(n.FinallyClause, writer);
        }

        public virtual void WriteCheckedStatement(CheckedStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("checked\n");
            WriteBlock(n.Body, writer);
        }

        public virtual void WriteUncheckedStatement(UncheckedStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("unchecked\n");
            WriteBlock(n.Body, writer);
        }

        public virtual void WriteLockStatement(LockStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("lock (");
            WriteExpression(n.Value, writer);
            writer.Write(")\n");
            WriteCompoundStatementBody(n.Body, writer);
        }

        public virtual void WriteUsingStatement(UsingStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("using (");
            WriteResourceAcquisition(n.Acquisition, writer);
            writer.Write(")\n");
            if (n.Body.Body.IsUsing)
                WriteUsingStatement(n.Body.Body.AsUsing, writer);
            else
                WriteCompoundStatementBody(n.Body, writer);
        }

        public virtual void WriteYieldReturnStatement(YieldReturnStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("yield return ");
            WriteExpression(n.Value, writer);
            writer.Write(";\n");
        }

        public virtual void WriteYieldBreakStatement(YieldBreakStatement n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("yield break;\n");
        }

        public virtual void WriteCompoundStatementBody(CompoundStatementBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (!n.Body.IsBlock)
                writer.OpenBlock();
            WriteEmbeddedStatement(n.Body, writer);
            if (!n.Body.IsBlock)
                writer.CloseBlock();
        }

        public virtual void WriteBlock(Block n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteBlock(n, writer, false);
        }

        public virtual void WriteBlock(Block n, IndentedWriter writer, bool inline)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.OpenCurlyBlock();
            if (n.Statements != null)
                WriteStatementList(n.Statements, writer);
            if (inline)
            {
                writer.Write("}");
                writer.CloseBlock();
            }
            else
            {
                writer.CloseCurlyBlock();
            }
        }

        public virtual void WriteStatementList(StatementList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (Statement item in n.Items)
                WriteStatement(item, writer);
        }

        public virtual void WriteLocalVariableDeclaration(LocalVariableDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteLocalVariableType(n.Type, writer);
            writer.Write(" ");
            WriteLocalVariableDeclarators(n.Declarators, writer);
        }

        public virtual void WriteSpecificLocalVariableType(SpecificLocalVariableType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteType(n.Type, writer);
        }

        public virtual void WriteVarLocalVariableType(VarLocalVariableType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("var");
        }

        public virtual void WriteLocalVariableDeclarators(LocalVariableDeclarators n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteLocalVariableDeclarator(n.Items[i], writer);
            }
        }

        public virtual void WriteLocalVariableDeclarator(LocalVariableDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            if (n.Initializer != null)
            {
                writer.Write(" = ");
                WriteLocalVariableInitializer(n.Initializer, writer);
            }
        }

        public virtual void WriteSingleLocalVariableInitializer(SingleLocalVariableInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer, NonAssignmentExpressionOpPrecedence);
        }

        public virtual void WriteMultipleLocalVariableInitializer(MultipleLocalVariableInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("{");
            writer.Write(" ");
            WriteArrayInitializer(n.Values, writer);
            writer.Write(" ");
            writer.Write("}");
        }

        public virtual void WriteLocalConstantDeclaration(LocalConstantDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("const ");
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteConstantDeclarators(n.Declarators, writer);
        }

        public virtual void WriteStatementExpression(StatementExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer, d);
        }

        public virtual void WriteSwitchBlock(SwitchBlock n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.OpenCurlyBlock();
            if (n.Sections != null)
                WriteSwitchSections(n.Sections, writer);
            writer.CloseCurlyBlock();
        }

        public virtual void WriteSwitchSections(SwitchSections n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (SwitchSection item in n.Items)
                WriteSwitchSection(item, writer);
        }

        public virtual void WriteSwitchSection(SwitchSection n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSwitchLabels(n.Labels, writer);
            writer.OpenBlock();
            WriteStatementList(n.Statements, writer);
            writer.CloseBlock();
        }

        public virtual void WriteSwitchLabels(SwitchLabels n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (SwitchLabel item in n.Items)
                WriteSwitchLabel(item, writer);
        }

        public virtual void WriteCaseSwitchLabel(CaseSwitchLabel n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("case ");
            WriteConstantExpression(n.Value, writer);
            writer.Write(":\n");
        }

        public virtual void WriteDefaultSwitchLabel(DefaultSwitchLabel n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("default:\n");
        }

        public virtual void WriteLocalVariableDeclarationForInitializer(LocalVariableDeclarationForInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteLocalVariableDeclaration(n.Declaration, writer);
        }

        public virtual void WriteStatementExpressionListForInitializer(StatementExpressionListForInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteStatementExpressionList(n.Expressions, writer);
        }

        public virtual void WriteForCondition(ForCondition n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteBooleanExpression(n.Value, writer);
        }

        public virtual void WriteForIterator(ForIterator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteStatementExpressionList(n.Expressions, writer);
        }

        public virtual void WriteStatementExpressionList(StatementExpressionList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteStatementExpression(n.Items[i], writer);
            }
        }

        public virtual void WriteAllSpecificCatchClauseList(AllSpecificCatchClauseList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSpecificCatchClauses(n.Specific, writer);
        }

        public virtual void WriteWithGeneralCatchClauseList(WithGeneralCatchClauseList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Specific != null)
                WriteSpecificCatchClauses(n.Specific, writer);
            WriteGeneralCatchClause(n.General, writer);
        }

        public virtual void WriteSpecificCatchClauses(SpecificCatchClauses n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (SpecificCatchClause item in n.Items)
                WriteSpecificCatchClause(item, writer);
        }

        public virtual void WriteSpecificCatchClause(SpecificCatchClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("catch (");
            WriteType(n.Type, writer);
            if (n.Name != null)
            {
                writer.Write(" ");
                WriteIdentifier(n.Name, writer);
            }
            writer.Write(")\n");
            WriteBlock(n.Body, writer);
        }

        public virtual void WriteGeneralCatchClause(GeneralCatchClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("catch\n");
            WriteBlock(n.Body, writer);
        }

        public virtual void WriteFinallyClause(FinallyClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("finally\n");
            WriteBlock(n.Body, writer);
        }

        public virtual void WriteDeclarationResourceAcquisition(DeclarationResourceAcquisition n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteLocalVariableDeclaration(n.Declaration, writer);
        }

        public virtual void WriteExpressionResourceAcquisition(ExpressionResourceAcquisition n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Expression, writer);
        }
        #endregion

        #region P504 B.2.6 Namespaces
        public virtual void WriteCompilationUnit(CompilationUnit n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.ExternAliases != null)
                WriteExternAliasDirectives(n.ExternAliases, writer);
            if (n.Usings != null)
            {
                if (n.ExternAliases != null)
                    writer.Write("\n");
                WriteUsingDirectives(n.Usings, writer);
            }
            if (n.Attributes != null)
            {
                if (n.ExternAliases != null || n.Usings != null)
                    writer.Write("\n");
                WriteGlobalAttributes(n.Attributes, writer);
            }
            if (n.Members != null)
            {
                if (n.ExternAliases != null || n.Usings != null || n.Attributes != null)
                    writer.Write("\n");
                WriteNamespaceMemberDeclarations(n.Members, writer);
            }
        }

        public virtual void WriteNamespaceDeclaration(NamespaceDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("namespace ");
            WriteQualifiedIdentifier(n.Name, writer);
            writer.Write("\n");
            WriteNamespaceBody(n.Body, writer, n.HasTrailingSemicolon ?? false);
        }

        public virtual void WriteSimpleQualifiedIdentifier(SimpleQualifiedIdentifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
        }

        public virtual void WriteCompoundQualifiedIdentifier(CompoundQualifiedIdentifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteQualifiedIdentifier(n.Name, writer);
            writer.Write(".");
            WriteIdentifier(n.Member, writer);
        }

        public virtual void WriteNamespaceBody(NamespaceBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteNamespaceBody(n, writer, false);
        }

        public virtual void WriteNamespaceBody(NamespaceBody n, IndentedWriter writer, bool hasTrailingSemicolon)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.OpenCurlyBlock();
            if (n.ExternAliases != null)
                WriteExternAliasDirectives(n.ExternAliases, writer);
            if (n.Usings != null)
            {
                if (n.ExternAliases != null)
                    writer.Write("\n");
                WriteUsingDirectives(n.Usings, writer);
            }
            if (n.Members != null)
            {
                if (n.ExternAliases != null || n.Usings != null)
                    writer.Write("\n");
                WriteNamespaceMemberDeclarations(n.Members, writer);
            }
            if (hasTrailingSemicolon)
                writer.CloseBlock(";");
            else
                writer.CloseCurlyBlock();
        }

        public virtual void WriteExternAliasDirectives(ExternAliasDirectives n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (ExternAliasDirective item in n.Items)
                WriteExternAliasDirective(item, writer);
        }

        public virtual void WriteExternAliasDirective(ExternAliasDirective n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("extern alias ");
            WriteIdentifier(n.Name, writer);
            writer.Write(";\n");
        }

        public virtual void WriteUsingDirectives(UsingDirectives n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (UsingDirective item in n.Items)
                WriteUsingDirective(item, writer);
        }

        public virtual void WriteAliasUsingDirective(AliasUsingDirective n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteUsingAliasDirective(n.Directive, writer);
        }

        public virtual void WriteNamespaceUsingDirective(NamespaceUsingDirective n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteUsingNamespaceDirective(n.Directive, writer);
        }

        public virtual void WriteUsingAliasDirective(UsingAliasDirective n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("using ");
            WriteIdentifier(n.Alias, writer);
            writer.Write(" = ");
            WriteNamespaceOrTypeName(n.Name, writer);
            writer.Write(";\n");
        }

        public virtual void WriteUsingNamespaceDirective(UsingNamespaceDirective n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("using ");
            WriteNamespaceName(n.Name, writer);
            writer.Write(";\n");
        }

        public virtual void WriteNamespaceMemberDeclarations(NamespaceMemberDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write("\n");
                WriteNamespaceMemberDeclaration(n.Items[i], writer);
            }
        }

        public virtual void WriteNamespaceNamespaceMemberDeclaration(NamespaceNamespaceMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteNamespaceDeclaration(n.Declaration, writer);
        }

        public virtual void WriteTypeNamespaceMemberDeclaration(TypeNamespaceMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeDeclaration(n.Declaration, writer);
        }

        public virtual void WriteClassTypeDeclaration(ClassTypeDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteClassDeclaration(n.Declaration, writer);
        }

        public virtual void WriteStructTypeDeclaration(StructTypeDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteStructDeclaration(n.Declaration, writer);
        }

        public virtual void WriteInterfaceTypeDeclaration(InterfaceTypeDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceDeclaration(n.Declaration, writer);
        }

        public virtual void WriteEnumTypeDeclaration(EnumTypeDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteEnumDeclaration(n.Declaration, writer);
        }

        public virtual void WriteDelegateTypeDeclaration(DelegateTypeDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteDelegateDeclaration(n.Declaration, writer);
        }

        public virtual void WriteQualifiedAliasMember(QualifiedAliasMember n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Scope, writer);
            writer.Write("::");
            WriteIdentifier(n.Member, writer);
            if (n.TypeArguments != null)
                WriteTypeArgumentList(n.TypeArguments, writer);
        }
        #endregion

        #region P505 B.2.7 Classes
        public virtual void WriteClassDeclaration(ClassDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteClassModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            if (n.IsPartial)
                writer.Write("partial ");
            writer.Write("class ");
            WriteIdentifier(n.Name, writer);
            if (n.TypeParameters != null)
                WriteTypeParameterList(n.TypeParameters, writer);
            if (n.Base != null)
            {
                writer.Write(" ");
                WriteClassBase(n.Base, writer);
            }
            if (n.Constraints != null)
            {
                writer.Write(" ");
                WriteTypeParameterConstraintsClauses(n.Constraints, writer);
            }
            writer.Write("\n");
            WriteClassBody(n.Body, writer, n.HasTrailingSemicolon ?? false);
        }

        public virtual void WriteClassModifiers(ClassModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteClassModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewClassModifier(NewClassModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicClassModifier(PublicClassModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedClassModifier(ProtectedClassModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalClassModifier(InternalClassModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateClassModifier(PrivateClassModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteAbstractClassModifier(AbstractClassModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("abstract");
        }

        public virtual void WriteSealedClassModifier(SealedClassModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("sealed");
        }

        public virtual void WriteStaticClassModifier(StaticClassModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("static");
        }

        public virtual void WriteTypeParameterList(TypeParameterList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeParameters(n.Parameters, writer);
        }

        public virtual void WriteTypeParameters(TypeParameters n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteTypeParameter(n.Items[i], writer);
            }
        }

        public virtual void WriteTypeParameter(TypeParameter n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
            {
                WriteAttributes(n.Attributes, writer);
                writer.Write(" ");
            }
            WriteIdentifier(n.Name, writer);
        }

        public virtual void WriteClassTypeOnlyClassBase(ClassTypeOnlyClassBase n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(": ");
            WriteClassType(n.Type, writer);
        }

        public virtual void WriteInterfaceTypeListOnlyClassBase(InterfaceTypeListOnlyClassBase n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(": ");
            WriteInterfaceTypeList(n.Types, writer);
        }

        public virtual void WriteClassTypeAndInterfaceTypeListClassBase(ClassTypeAndInterfaceTypeListClassBase n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(": ");
            WriteClassType(n.Type, writer);
            writer.Write(", ");
            WriteInterfaceTypeList(n.Types, writer);
        }

        public virtual void WriteInterfaceTypeList(InterfaceTypeList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteInterfaceType(n.Items[i], writer);
            }
        }

        public virtual void WriteTypeParameterConstraintsClauses(TypeParameterConstraintsClauses n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteTypeParameterConstraintsClause(n.Items[i], writer);
            }
        }

        public virtual void WriteTypeParameterConstraintsClause(TypeParameterConstraintsClause n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("where ");
            WriteIdentifier(n.Parameter, writer);
            writer.Write(" : ");
            WriteTypeParameterConstraints(n.Constraints, writer);
        }

        public virtual void WritePrimaryConstraintOnlyTypeParameterConstraints(PrimaryConstraintOnlyTypeParameterConstraints n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WritePrimaryConstraint(n.Primary, writer);
        }

        public virtual void WriteSecondaryConstraintsOnlyTypeParameterConstraints(SecondaryConstraintsOnlyTypeParameterConstraints n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSecondaryConstraints(n.Secondary, writer);
        }

        public virtual void WriteConstructorConstraintOnlyTypeParameterConstraints(ConstructorConstraintOnlyTypeParameterConstraints n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteConstructorConstraint(n.Constructor, writer);
        }

        public virtual void WritePrimaryAndSecondaryConstraintsTypeParameterConstraints(PrimaryAndSecondaryConstraintsTypeParameterConstraints n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WritePrimaryConstraint(n.Primary, writer);
            writer.Write(", ");
            WriteSecondaryConstraints(n.Secondary, writer);
        }

        public virtual void WritePrimaryAndConstructorConstraintsTypeParameterConstraints(PrimaryAndConstructorConstraintsTypeParameterConstraints n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WritePrimaryConstraint(n.Primary, writer);
            writer.Write(", ");
            WriteConstructorConstraint(n.Constructor, writer);
        }

        public virtual void WriteSecondaryAndConstructorConstraintsTypeParameterConstraints(SecondaryAndConstructorConstraintsTypeParameterConstraints n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSecondaryConstraints(n.Secondary, writer);
            writer.Write(", ");
            WriteConstructorConstraint(n.Constructor, writer);
        }

        public virtual void WritePrimarySecondaryAndConstructorConstraintsTypeParameterConstraints(PrimarySecondaryAndConstructorConstraintsTypeParameterConstraints n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WritePrimaryConstraint(n.Primary, writer);
            writer.Write(", ");
            WriteSecondaryConstraints(n.Secondary, writer);
            writer.Write(", ");
            WriteConstructorConstraint(n.Constructor, writer);
        }

        public virtual void WriteClassTypePrimaryConstraint(ClassTypePrimaryConstraint n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteClassType(n.Type, writer);
        }

        public virtual void WriteClassPrimaryConstraint(ClassPrimaryConstraint n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("class");
        }

        public virtual void WriteStructPrimaryConstraint(StructPrimaryConstraint n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("struct");
        }

        public virtual void WriteSecondaryConstraints(SecondaryConstraints n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteSecondaryConstraint(n.Items[i], writer);
            }
        }

        public virtual void WriteInterfaceTypeSecondaryConstraint(InterfaceTypeSecondaryConstraint n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceType(n.Type, writer);
        }

        public virtual void WriteTypeParameterSecondaryConstraint(TypeParameterSecondaryConstraint n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Parameter, writer);
        }

        public virtual void WriteConstructorConstraint(ConstructorConstraint n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new ()");
        }

        public virtual void WriteClassBody(ClassBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteClassBody(n, writer, false);
        }

        public virtual void WriteClassBody(ClassBody n, IndentedWriter writer, bool hasTrailingSemicolon)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.OpenCurlyBlock();
            if (n.Declarations != null)
                WriteClassMemberDeclarations(n.Declarations, writer);
            if (hasTrailingSemicolon)
                writer.CloseBlock(";");
            else
                writer.CloseCurlyBlock();
        }

        public virtual void WriteClassMemberDeclarations(ClassMemberDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0 && n.Items[i - 1].Tag != n.Items[i].Tag)
                    writer.Write("\n");
                WriteClassMemberDeclaration(n.Items[i], writer);
            }
        }

        public virtual void WriteConstantClassMemberDeclaration(ConstantClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteConstantDeclaration(n.Declaration, writer);
        }

        public virtual void WriteFieldClassMemberDeclaration(FieldClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteFieldDeclaration(n.Declaration, writer);
        }

        public virtual void WriteMethodClassMemberDeclaration(MethodClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteMethodDeclaration(n.Declaration, writer);
        }

        public virtual void WritePropertyClassMemberDeclaration(PropertyClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WritePropertyDeclaration(n.Declaration, writer);
        }

        public virtual void WriteEventClassMemberDeclaration(EventClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteEventDeclaration(n.Declaration, writer);
        }

        public virtual void WriteIndexerClassMemberDeclaration(IndexerClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIndexerDeclaration(n.Declaration, writer);
        }

        public virtual void WriteOperatorClassMemberDeclaration(OperatorClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteOperatorDeclaration(n.Declaration, writer);
        }

        public virtual void WriteConstructorClassMemberDeclaration(ConstructorClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteConstructorDeclaration(n.Declaration, writer);
        }

        public virtual void WriteDestructorClassMemberDeclaration(DestructorClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteDestructorDeclaration(n.Declaration, writer);
        }

        public virtual void WriteStaticConstructorClassMemberDeclaration(StaticConstructorClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteStaticConstructorDeclaration(n.Declaration, writer);
        }

        public virtual void WriteTypeClassMemberDeclaration(TypeClassMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeDeclaration(n.Declaration, writer);
        }

        public virtual void WriteConstantDeclaration(ConstantDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteConstantModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            writer.Write("const ");
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteConstantDeclarators(n.Declarators, writer);
            writer.Write(";\n");
        }

        public virtual void WriteConstantModifiers(ConstantModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteConstantModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewConstantModifier(NewConstantModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicConstantModifier(PublicConstantModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedConstantModifier(ProtectedConstantModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalConstantModifier(InternalConstantModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateConstantModifier(PrivateConstantModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteConstantDeclarators(ConstantDeclarators n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteConstantDeclarator(n.Items[i], writer);
            }
        }

        public virtual void WriteConstantDeclarator(ConstantDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            writer.Write(" = ");
            WriteConstantExpression(n.Value, writer);
        }

        public virtual void WriteFieldDeclaration(FieldDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteFieldModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteVariableDeclarators(n.Declarators, writer);
            writer.Write(";\n");
        }

        public virtual void WriteFieldModifiers(FieldModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteFieldModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewFieldModifier(NewFieldModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicFieldModifier(PublicFieldModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedFieldModifier(ProtectedFieldModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalFieldModifier(InternalFieldModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateFieldModifier(PrivateFieldModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteStaticFieldModifier(StaticFieldModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("static");
        }

        public virtual void WriteReadonlyFieldModifier(ReadonlyFieldModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("readonly");
        }

        public virtual void WriteVolatileFieldModifier(VolatileFieldModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("volatile");
        }

        public virtual void WriteVariableDeclarators(VariableDeclarators n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteVariableDeclarator(n.Items[i], writer);
            }
        }

        public virtual void WriteVariableDeclarator(VariableDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            if (n.Value != null)
            {
                writer.Write(" = ");
                WriteVariableInitializer(n.Value, writer);
            }
        }

        public virtual void WriteSingleVariableInitializer(SingleVariableInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer);
        }

        public virtual void WriteMultipleVariableInitializer(MultipleVariableInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteArrayInitializer(n.Values, writer);
        }

        public virtual void WriteMethodDeclaration(MethodDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteMethodHeader(n.Header, writer);
            WriteMethodBody(n.Body, writer);
        }

        public virtual void WriteMethodHeader(MethodHeader n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteMethodModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            if (n.IsPartial)
                writer.Write("partial ");
            WriteReturnType(n.ReturnType, writer);
            writer.Write(" ");
            WriteMemberName(n.Name, writer);
            if (n.TypeParameters != null)
                WriteTypeParameterList(n.TypeParameters, writer);
            writer.Write("(");
            if (n.FormalParameters != null)
                WriteFormalParameterList(n.FormalParameters, writer);
            writer.Write(")");
            if (n.Constraints != null)
            {
                writer.Write(" ");
                WriteTypeParameterConstraintsClauses(n.Constraints, writer);
            }
        }

        public virtual void WriteMethodModifiers(MethodModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteMethodModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewMethodModifier(NewMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicMethodModifier(PublicMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedMethodModifier(ProtectedMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalMethodModifier(InternalMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateMethodModifier(PrivateMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteStaticMethodModifier(StaticMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("static");
        }

        public virtual void WriteVirtualMethodModifier(VirtualMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("virtual");
        }

        public virtual void WriteSealedMethodModifier(SealedMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("sealed");
        }

        public virtual void WriteOverrideMethodModifier(OverrideMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("override");
        }

        public virtual void WriteAbstractMethodModifier(AbstractMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("abstract");
        }

        public virtual void WriteExternMethodModifier(ExternMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("extern");
        }

        public virtual void WriteAsyncMethodModifier(AsyncMethodModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("async");
        }

        public virtual void WriteValuedReturnType(ValuedReturnType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteType(n.Type, writer);
        }

        public virtual void WriteVoidReturnType(VoidReturnType n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("void");
        }

        public virtual void WriteSimpleMemberName(SimpleMemberName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
        }

        public virtual void WriteExplicitMemberName(ExplicitMemberName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceType(n.Target, writer);
            writer.Write(".");
            WriteIdentifier(n.Name, writer);
        }

        public virtual void WriteFullMethodBody(FullMethodBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("\n");
            WriteBlock(n.Block, writer);
        }

        public virtual void WriteFastMethodBody(FastMethodBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(" => ");
            WriteExpression(n.Value, writer);
            writer.Write(";\n");
        }

        public virtual void WritePartialMethodBody(PartialMethodBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(";\n");
        }

        public virtual void WriteFixedOnlyFormalParameterList(FixedOnlyFormalParameterList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteFixedParameters(n.Fixed, writer);
        }

        public virtual void WriteParamsOnlyFormalParameterList(ParamsOnlyFormalParameterList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteParameterArray(n.Params, writer);
        }

        public virtual void WriteFixedAndParamsFormalParameterList(FixedAndParamsFormalParameterList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteFixedParameters(n.Fixed, writer);
            writer.Write(", ");
            WriteParameterArray(n.Params, writer);
        }

        public virtual void WriteFixedParameters(FixedParameters n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteFixedParameter(n.Items[i], writer);
            }
        }

        public virtual void WriteFixedParameter(FixedParameter n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
            {
                WriteAttributes(n.Attributes, writer, true);
                writer.Write(" ");
            }
            if (n.Modifier != null)
            {
                WriteParameterModifier(n.Modifier, writer);
                writer.Write(" ");
            }
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteIdentifier(n.Name, writer);
            if (n.Default != null)
            {
                writer.Write(" ");
                WriteDefaultArgument(n.Default, writer);
            }
        }

        public virtual void WriteDefaultArgument(DefaultArgument n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("= ");
            WriteExpression(n.Value, writer);
        }

        public virtual void WriteRefParameterModifier(RefParameterModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("ref");
        }

        public virtual void WriteOutParameterModifier(OutParameterModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("out");
        }

        public virtual void WriteThisParameterModifier(ThisParameterModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("this");
        }

        public virtual void WriteParameterArray(ParameterArray n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
            {
                WriteAttributes(n.Attributes, writer, true);
                writer.Write(" ");
            }
            writer.Write("params ");
            WriteArrayType(n.Type, writer);
            writer.Write(" ");
            WriteIdentifier(n.Name, writer);
        }

        public virtual void WritePropertyDeclaration(PropertyDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WritePropertyModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteMemberName(n.Name, writer);
            WritePropertyBody(n.Body, writer);
        }

        public virtual void WritePropertyModifiers(PropertyModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WritePropertyModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewPropertyModifier(NewPropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicPropertyModifier(PublicPropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedPropertyModifier(ProtectedPropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalPropertyModifier(InternalPropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivatePropertyModifier(PrivatePropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteStaticPropertyModifier(StaticPropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("static");
        }

        public virtual void WriteVirtualPropertyModifier(VirtualPropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("virtual");
        }

        public virtual void WriteSealedPropertyModifier(SealedPropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("sealed");
        }

        public virtual void WriteOverridePropertyModifier(OverridePropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("override");
        }

        public virtual void WriteAbstractPropertyModifier(AbstractPropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("abstract");
        }

        public virtual void WriteExternPropertyModifier(ExternPropertyModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("extern");
        }

        private static bool AccessorBodyHasCustomLogic(AccessorBody n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return !n.IsPartial;
        }

        private static bool AccessorDeclarationsHaveCustomLogic(AccessorDeclarations n)
        {
            if (n.IsGetOnly && AccessorBodyHasCustomLogic(n.AsGetOnly.Getter.Body))
                return true;
            if (n.IsSetOnly && AccessorBodyHasCustomLogic(n.AsSetOnly.Setter.Body))
                return true;
            if (n.IsGetSet && (AccessorBodyHasCustomLogic(n.AsGetSet.Getter.Body) || AccessorBodyHasCustomLogic(n.AsGetSet.Setter.Body)))
                return true;
            if (n.IsSetGet && (AccessorBodyHasCustomLogic(n.AsSetGet.Setter.Body) || AccessorBodyHasCustomLogic(n.AsSetGet.Getter.Body)))
                return true;
            return false;
        }

        public virtual void WriteFullPropertyBody(FullPropertyBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (AccessorDeclarationsHaveCustomLogic(n.Accessors))
            {
                writer.Write("\n");
                writer.OpenCurlyBlock();
                WriteAccessorDeclarations(n.Accessors, writer);
                writer.CloseCurlyBlock();
            }
            else
            {
                writer.Write(" { ");
                WriteAccessorDeclarations(n.Accessors, writer);
                writer.Write(" }");
                if (n.Initializer != null)
                {
                    writer.Write(" ");
                    WritePropertyInitializer(n.Initializer, writer);
                }
                writer.Write("\n");
            }
        }

        public virtual void WriteFastPropertyBody(FastPropertyBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(" => ");
            WriteExpression(n.Value, writer);
            writer.Write(";\n");
        }

        public virtual void WritePropertyInitializer(PropertyInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("= ");
            WriteVariableInitializer(n.Value, writer);
        }

        public virtual void WriteProtectedAccessorModifier(ProtectedAccessorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalAccessorModifier(InternalAccessorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateAccessorModifier(PrivateAccessorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteProtectedInternalAccessorModifier(ProtectedInternalAccessorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected internal");
        }

        public virtual void WriteInternalProtectedAccessorModifier(InternalProtectedAccessorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal protected");
        }

        public virtual void WriteGetOnlyAccessorDeclarations(GetOnlyAccessorDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteGetAccessorDeclaration(n.Getter, writer);
        }

        public virtual void WriteSetOnlyAccessorDeclarations(SetOnlyAccessorDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSetAccessorDeclaration(n.Setter, writer);
        }

        public virtual void WriteGetSetAccessorDeclarations(GetSetAccessorDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteGetAccessorDeclaration(n.Getter, writer);
            if (!AccessorDeclarationsHaveCustomLogic(n))
                writer.Write(" ");
            WriteSetAccessorDeclaration(n.Setter, writer);
        }

        public virtual void WriteSetGetAccessorDeclarations(SetGetAccessorDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteSetAccessorDeclaration(n.Setter, writer);
            if (!AccessorDeclarationsHaveCustomLogic(n))
                writer.Write(" ");
            WriteGetAccessorDeclaration(n.Getter, writer);
        }

        public virtual void WriteGetAccessorDeclaration(GetAccessorDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            bool horizontally = !AccessorBodyHasCustomLogic(n.Body);
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer, horizontally);
            if (n.Modifier != null)
            {
                WriteAccessorModifier(n.Modifier, writer);
                writer.Write(" ");
            }
            writer.Write("get");
            WriteAccessorBody(n.Body, writer);
        }

        public virtual void WriteSetAccessorDeclaration(SetAccessorDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            bool horizontally = !AccessorBodyHasCustomLogic(n.Body);
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer, horizontally);
            if (n.Modifier != null)
            {
                WriteAccessorModifier(n.Modifier, writer);
                writer.Write(" ");
            }
            writer.Write("set");
            WriteAccessorBody(n.Body, writer);
        }

        public virtual void WriteFullAccessorBody(FullAccessorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("\n");
            WriteBlock(n.Block, writer);
        }

        public virtual void WritePartialAccessorBody(PartialAccessorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(";");
        }

        public virtual void WriteAutoEventDeclaration(AutoEventDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteEventModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            writer.Write("event ");
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteVariableDeclarators(n.Declarators, writer);
            writer.Write(";\n");
        }

        public virtual void WriteExplicitEventDeclaration(ExplicitEventDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteEventModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            writer.Write("event ");
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteMemberName(n.Name, writer);
            writer.Write("\n");
            writer.OpenCurlyBlock();
            WriteEventAccessorDeclarations(n.Accessors, writer);
            writer.CloseCurlyBlock();
        }

        public virtual void WriteEventModifiers(EventModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteEventModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewEventModifier(NewEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicEventModifier(PublicEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedEventModifier(ProtectedEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalEventModifier(InternalEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateEventModifier(PrivateEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteStaticEventModifier(StaticEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("static");
        }

        public virtual void WriteVirtualEventModifier(VirtualEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("virtual");
        }

        public virtual void WriteSealedEventModifier(SealedEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("sealed");
        }

        public virtual void WriteOverrideEventModifier(OverrideEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("override");
        }

        public virtual void WriteAbstractEventModifier(AbstractEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("abstract");
        }

        public virtual void WriteExternEventModifier(ExternEventModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("extern");
        }

        public virtual void WriteAddAccessorDeclaration(AddAccessorDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            writer.Write("add\n");
            WriteBlock(n.Block, writer);
        }

        public virtual void WriteRemoveAccessorDeclaration(RemoveAccessorDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            writer.Write("remove\n");
            WriteBlock(n.Block, writer);
        }

        public virtual void WriteAddOnlyEventAccessorDeclarations(AddOnlyEventAccessorDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteAddAccessorDeclaration(n.Add, writer);
        }

        public virtual void WriteRemoveOnlyEventAccessorDeclarations(RemoveOnlyEventAccessorDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteRemoveAccessorDeclaration(n.Remove, writer);
        }

        public virtual void WriteAddRemoveEventAccessorDeclarations(AddRemoveEventAccessorDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteAddAccessorDeclaration(n.Add, writer);
            WriteRemoveAccessorDeclaration(n.Remove, writer);
        }

        public virtual void WriteRemoveAddEventAccessorDeclarations(RemoveAddEventAccessorDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteRemoveAccessorDeclaration(n.Remove, writer);
            WriteAddAccessorDeclaration(n.Add, writer);
        }

        public virtual void WriteIndexerDeclaration(IndexerDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteIndexerModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            WriteIndexerDeclarator(n.Declarator, writer);
            WriteIndexerBody(n.Body, writer);
        }

        public virtual void WriteIndexerModifiers(IndexerModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteIndexerModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewIndexerModifier(NewIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicIndexerModifier(PublicIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedIndexerModifier(ProtectedIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalIndexerModifier(InternalIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateIndexerModifier(PrivateIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteVirtualIndexerModifier(VirtualIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("virtual");
        }

        public virtual void WriteSealedIndexerModifier(SealedIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("sealed");
        }

        public virtual void WriteOverrideIndexerModifier(OverrideIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("override");
        }

        public virtual void WriteAbstractIndexerModifier(AbstractIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("abstract");
        }

        public virtual void WriteExternIndexerModifier(ExternIndexerModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("extern");
        }

        public virtual void WriteSimpleIndexerDeclarator(SimpleIndexerDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteType(n.Type, writer);
            writer.Write(" this[");
            WriteFormalParameterList(n.FormalParameters, writer);
            writer.Write("]");
        }

        public virtual void WriteExplicitIndexerDeclarator(ExplicitIndexerDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteInterfaceType(n.Target, writer);
            writer.Write(".this[");
            WriteFormalParameterList(n.FormalParameters, writer);
            writer.Write("]");
        }

        public virtual void WriteFullIndexerBody(FullIndexerBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (AccessorDeclarationsHaveCustomLogic(n.Accessors))
            {
                writer.Write("\n");
                writer.OpenCurlyBlock();
                WriteAccessorDeclarations(n.Accessors, writer);
                writer.CloseCurlyBlock();
            }
            else
            {
                writer.Write(" { ");
                WriteAccessorDeclarations(n.Accessors, writer);
                writer.Write(" }");
                writer.Write("\n");
            }
        }

        public virtual void WriteFastIndexerBody(FastIndexerBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(" => ");
            WriteExpression(n.Value, writer);
            writer.Write(";\n");
        }

        public virtual void WriteOperatorDeclaration(OperatorDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            WriteOperatorModifiers(n.Modifiers, writer);
            writer.Write(" ");
            WriteOperatorDeclarator(n.Declarator, writer);
            WriteOperatorBody(n.Body, writer);
        }

        public virtual void WriteOperatorModifiers(OperatorModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteOperatorModifier(n.Items[i], writer);
            }
        }

        public virtual void WritePublicOperatorModifier(PublicOperatorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteStaticOperatorModifier(StaticOperatorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("static");
        }

        public virtual void WriteExternOperatorModifier(ExternOperatorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("extern");
        }

        public virtual void WriteUnaryOperatorDeclarator(UnaryOperatorDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteType(n.ResultType, writer);
            writer.Write(" operator ");
            WriteOverloadableUnaryOperator(n.Operator, writer);
            writer.Write("(");
            WriteType(n.ParameterType, writer);
            writer.Write(" ");
            WriteIdentifier(n.ParameterName, writer);
            writer.Write(")");
        }

        public virtual void WriteBinaryOperatorDeclarator(BinaryOperatorDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteType(n.ResultType, writer);
            writer.Write(" operator ");
            WriteOverloadableBinaryOperator(n.Operator, writer);
            writer.Write("(");
            WriteType(n.LeftType, writer);
            writer.Write(" ");
            WriteIdentifier(n.LeftName, writer);
            writer.Write(", ");
            WriteType(n.RightType, writer);
            writer.Write(" ");
            WriteIdentifier(n.RightName, writer);
            writer.Write(")");
        }

        public virtual void WriteImplicitConversionOperatorDeclarator(ImplicitConversionOperatorDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("implicit operator ");
            WriteType(n.ResultType, writer);
            writer.Write("(");
            WriteType(n.ParameterType, writer);
            writer.Write(" ");
            WriteIdentifier(n.ParameterName, writer);
            writer.Write(")");
        }

        public virtual void WriteExplicitConversionOperatorDeclarator(ExplicitConversionOperatorDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("explicit operator ");
            WriteType(n.ResultType, writer);
            writer.Write("(");
            WriteType(n.ParameterType, writer);
            writer.Write(" ");
            WriteIdentifier(n.ParameterName, writer);
            writer.Write(")");
        }

        public virtual void WritePositiveOverloadableUnaryOperator(PositiveOverloadableUnaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("+");
        }

        public virtual void WriteNegativeOverloadableUnaryOperator(NegativeOverloadableUnaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("-");
        }

        public virtual void WriteLogicalNotOverloadableUnaryOperator(LogicalNotOverloadableUnaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("!");
        }

        public virtual void WriteBitwiseNotOverloadableUnaryOperator(BitwiseNotOverloadableUnaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("~");
        }

        public virtual void WriteIncrementOverloadableUnaryOperator(IncrementOverloadableUnaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("++");
        }

        public virtual void WriteDecrementOverloadableUnaryOperator(DecrementOverloadableUnaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("--");
        }

        public virtual void WriteTrueOverloadableUnaryOperator(TrueOverloadableUnaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("true");
        }

        public virtual void WriteFalseOverloadableUnaryOperator(FalseOverloadableUnaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("false");
        }

        public virtual void WriteMultiplyOverloadableBinaryOperator(MultiplyOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("*");
        }

        public virtual void WriteDivideOverloadableBinaryOperator(DivideOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("/");
        }

        public virtual void WriteModuloOverloadableBinaryOperator(ModuloOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("%");
        }

        public virtual void WriteAddOverloadableBinaryOperator(AddOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("+");
        }

        public virtual void WriteSubtractOverloadableBinaryOperator(SubtractOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("-");
        }

        public virtual void WriteLeftShiftOverloadableBinaryOperator(LeftShiftOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("<<");
        }

        public virtual void WriteRightShiftOverloadableBinaryOperator(RightShiftOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(">>");
        }

        public virtual void WriteLessThanOverloadableBinaryOperator(LessThanOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("<");
        }

        public virtual void WriteGreaterThanOverloadableBinaryOperator(GreaterThanOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(">");
        }

        public virtual void WriteLessEqualOverloadableBinaryOperator(LessEqualOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("<=");
        }

        public virtual void WriteGreaterEqualOverloadableBinaryOperator(GreaterEqualOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(">=");
        }

        public virtual void WriteEqualToOverloadableBinaryOperator(EqualToOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("==");
        }

        public virtual void WriteNotEqualToOverloadableBinaryOperator(NotEqualToOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("!=");
        }

        public virtual void WriteBitwiseAndOverloadableBinaryOperator(BitwiseAndOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("&");
        }

        public virtual void WriteBitwiseXorOverloadableBinaryOperator(BitwiseXorOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("^");
        }

        public virtual void WriteBitwiseOrOverloadableBinaryOperator(BitwiseOrOverloadableBinaryOperator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("|");
        }

        public virtual void WriteFullOperatorBody(FullOperatorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("\n");
            WriteBlock(n.Block, writer);
        }

        public virtual void WriteFastOperatorBody(FastOperatorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(" => ");
            WriteExpression(n.Value, writer);
            writer.Write(";\n");
        }

        public virtual void WritePartialOperatorBody(PartialOperatorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(";\n");
        }

        public virtual void WriteConstructorDeclaration(ConstructorDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteConstructorModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            WriteConstructorDeclarator(n.Declarator, writer);
            WriteConstructorBody(n.Body, writer);
        }

        public virtual void WriteConstructorModifiers(ConstructorModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteConstructorModifier(n.Items[i], writer);
            }
        }

        public virtual void WritePublicConstructorModifier(PublicConstructorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedConstructorModifier(ProtectedConstructorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalConstructorModifier(InternalConstructorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateConstructorModifier(PrivateConstructorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteExternConstructorModifier(ExternConstructorModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("extern");
        }

        public virtual void WriteConstructorDeclarator(ConstructorDeclarator n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            writer.Write("(");
            if (n.FormalParameters != null)
                WriteFormalParameterList(n.FormalParameters, writer);
            writer.Write(")");
            if (n.Initializer != null)
            {
                writer.Write(" ");
                WriteConstructorInitializer(n.Initializer, writer);
            }
        }

        public virtual void WriteBaseConstructorInitializer(BaseConstructorInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(": base(");
            if (n.Arguments != null)
                WriteArgumentList(n.Arguments, writer);
            writer.Write(")");
        }

        public virtual void WriteThisConstructorInitializer(ThisConstructorInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(": this(");
            if (n.Arguments != null)
                WriteArgumentList(n.Arguments, writer);
            writer.Write(")");
        }

        public virtual void WriteFullConstructorBody(FullConstructorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("\n");
            WriteBlock(n.Block, writer);
        }

        public virtual void WritePartialConstructorBody(PartialConstructorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(";\n");
        }

        public virtual void WriteStaticConstructorDeclaration(StaticConstructorDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            WriteStaticConstructorModifiers(n.Modifiers, writer);
            writer.Write(" ");
            WriteIdentifier(n.Name, writer);
            writer.Write("()");
            WriteStaticConstructorBody(n.Body, writer);
        }

        public virtual void WriteExternStaticStaticConstructorModifiers(ExternStaticStaticConstructorModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.IsExtern)
                writer.Write("extern ");
            writer.Write("static");
        }

        public virtual void WriteStaticExternStaticConstructorModifiers(StaticExternStaticConstructorModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("static");
            if (n.IsExtern)
                writer.Write(" extern");
        }

        public virtual void WriteFullStaticConstructorBody(FullStaticConstructorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("\n");
            WriteBlock(n.Block, writer);
        }

        public virtual void WritePartialStaticConstructorBody(PartialStaticConstructorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(";\n");
        }

        public virtual void WriteDestructorDeclaration(DestructorDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.IsExtern)
                writer.Write("extern ");
            writer.Write("~");
            WriteIdentifier(n.Name, writer);
            writer.Write("()");
            WriteDestructorBody(n.Body, writer);
        }

        public virtual void WriteFullDestructorBody(FullDestructorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("\n");
            WriteBlock(n.Block, writer);
        }

        public virtual void WritePartialDestructorBody(PartialDestructorBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(";\n");
        }
        #endregion

        #region P512 B.2.8 Structs
        public virtual void WriteStructDeclaration(StructDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteStructModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            if (n.IsPartial)
                writer.Write("partial ");
            writer.Write("struct ");
            WriteIdentifier(n.Name, writer);
            if (n.TypeParameters != null)
                WriteTypeParameterList(n.TypeParameters, writer);
            if (n.Interfaces != null)
            {
                writer.Write(" ");
                WriteStructInterfaces(n.Interfaces, writer);
            }
            if (n.Constraints != null)
            {
                writer.Write(" ");
                WriteTypeParameterConstraintsClauses(n.Constraints, writer);
            }
            writer.Write("\n");
            WriteStructBody(n.Body, writer, n.HasTrailingSemicolon ?? false);
        }

        public virtual void WriteStructModifiers(StructModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteStructModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewStructModifier(NewStructModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicStructModifier(PublicStructModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedStructModifier(ProtectedStructModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalStructModifier(InternalStructModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateStructModifier(PrivateStructModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteStructInterfaces(StructInterfaces n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(": ");
            WriteInterfaceTypeList(n.Types, writer);
        }

        public virtual void WriteStructBody(StructBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteStructBody(n, writer, false);
        }

        public virtual void WriteStructBody(StructBody n, IndentedWriter writer, bool hasTrailingSemicolon)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.OpenCurlyBlock();
            if (n.Declarations != null)
                WriteStructMemberDeclarations(n.Declarations, writer);
            if (hasTrailingSemicolon)
                writer.CloseBlock(";");
            else
                writer.CloseCurlyBlock();
        }

        public virtual void WriteStructMemberDeclarations(StructMemberDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0 && n.Items[i - 1].Tag != n.Items[i].Tag)
                    writer.Write("\n");
                WriteStructMemberDeclaration(n.Items[i], writer);
            }
        }

        public virtual void WriteConstantStructMemberDeclaration(ConstantStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteConstantDeclaration(n.Declaration, writer);
        }

        public virtual void WriteFieldStructMemberDeclaration(FieldStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteFieldDeclaration(n.Declaration, writer);
        }

        public virtual void WriteMethodStructMemberDeclaration(MethodStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteMethodDeclaration(n.Declaration, writer);
        }

        public virtual void WritePropertyStructMemberDeclaration(PropertyStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WritePropertyDeclaration(n.Declaration, writer);
        }

        public virtual void WriteEventStructMemberDeclaration(EventStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteEventDeclaration(n.Declaration, writer);
        }

        public virtual void WriteIndexerStructMemberDeclaration(IndexerStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIndexerDeclaration(n.Declaration, writer);
        }

        public virtual void WriteOperatorStructMemberDeclaration(OperatorStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteOperatorDeclaration(n.Declaration, writer);
        }

        public virtual void WriteConstructorStructMemberDeclaration(ConstructorStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteConstructorDeclaration(n.Declaration, writer);
        }

        public virtual void WriteStaticConstructorStructMemberDeclaration(StaticConstructorStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteStaticConstructorDeclaration(n.Declaration, writer);
        }

        public virtual void WriteTypeStructMemberDeclaration(TypeStructMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeDeclaration(n.Declaration, writer);
        }
        #endregion

        #region P513 B.2.9 Arrays
        public virtual void WriteRankSpecifiers(RankSpecifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (RankSpecifier item in n.Items)
                WriteRankSpecifier(item, writer);
        }

        public virtual void WriteRankSpecifier(RankSpecifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("[");
            for (int i = 1; i < n.Rank; i++)
                writer.Write(",");
            writer.Write("]");
        }

        public virtual void WriteArrayInitializer(ArrayInitializer n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("{");
            writer.Write(" ");
            if (n.VariableInitializers != null)
            {
                WriteVariableInitializerList(n.VariableInitializers, writer);
                if (n.HasTrailingComma ?? false)
                    writer.Write(",");
                writer.Write(" ");
            }
            writer.Write("}");
        }

        public virtual void WriteVariableInitializerList(VariableInitializerList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            using (writer.ColumnAlignment)
            {
                for (int i = 0; i < n.Items.Count; i++)
                {
                    if (i > 0)
                    {
                        writer.Write(",");
                        if ((i + 1) % 10 == 0)
                            writer.Write("\n");
                        else
                            writer.Write(" ");
                    }
                    WriteVariableInitializer(n.Items[i], writer);
                }
            }
        }
        #endregion

        #region P513 B.2.10 Interfaces
        public virtual void WriteInterfaceDeclaration(InterfaceDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteInterfaceModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            if (n.IsPartial)
                writer.Write("partial ");
            writer.Write("interface ");
            WriteIdentifier(n.Name, writer);
            if (n.TypeParameters != null)
                WriteVariantTypeParameterList(n.TypeParameters, writer);
            if (n.Base != null)
            {
                writer.Write(" ");
                WriteInterfaceBase(n.Base, writer);
            }
            if (n.Constraints != null)
            {
                writer.Write(" ");
                WriteTypeParameterConstraintsClauses(n.Constraints, writer);
            }
            writer.Write("\n");
            WriteInterfaceBody(n.Body, writer, n.HasTrailingSemicolon ?? false);
        }

        public virtual void WriteInterfaceModifiers(InterfaceModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteInterfaceModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewInterfaceModifier(NewInterfaceModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicInterfaceModifier(PublicInterfaceModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedInterfaceModifier(ProtectedInterfaceModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalInterfaceModifier(InternalInterfaceModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateInterfaceModifier(PrivateInterfaceModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteVariantTypeParameterList(VariantTypeParameterList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("<");
            WriteVariantTypeParameters(n.Parameters, writer);
            writer.Write(">");
        }

        public virtual void WriteVariantTypeParameters(VariantTypeParameters n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteVariantTypeParameter(n.Items[i], writer);
            }
        }

        public virtual void WriteVariantTypeParameter(VariantTypeParameter n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
            {
                WriteAttributes(n.Attributes, writer);
                writer.Write(" ");
            }
            if (n.Annotation != null)
            {
                WriteVarianceAnnotation(n.Annotation, writer);
                writer.Write(" ");
            }
            WriteIdentifier(n.Name, writer);
        }

        public virtual void WriteInVarianceAnnotation(InVarianceAnnotation n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("in");
        }

        public virtual void WriteOutVarianceAnnotation(OutVarianceAnnotation n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("out");
        }

        public virtual void WriteInterfaceBase(InterfaceBase n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceTypeList(n.Types, writer);
        }

        public virtual void WriteInterfaceBody(InterfaceBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceBody(n, writer, false);
        }

        public virtual void WriteInterfaceBody(InterfaceBody n, IndentedWriter writer, bool hasTrailingSemicolon)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.OpenCurlyBlock();
            if (n.Declarations != null)
                WriteInterfaceMemberDeclarations(n.Declarations, writer);
            if (hasTrailingSemicolon)
                writer.CloseBlock(";");
            else
                writer.CloseCurlyBlock();
        }

        public virtual void WriteInterfaceMemberDeclarations(InterfaceMemberDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (InterfaceMemberDeclaration item in n.Items)
                WriteInterfaceMemberDeclaration(item, writer);
        }

        public virtual void WriteMethodInterfaceMemberDeclaration(MethodInterfaceMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceMethodDeclaration(n.Declaration, writer);
        }

        public virtual void WritePropertyInterfaceMemberDeclaration(PropertyInterfaceMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfacePropertyDeclaration(n.Declaration, writer);
        }

        public virtual void WriteEventInterfaceMemberDeclaration(EventInterfaceMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceEventDeclaration(n.Declaration, writer);
        }

        public virtual void WriteIndexerInterfaceMemberDeclaration(IndexerInterfaceMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceIndexerDeclaration(n.Declaration, writer);
        }

        public virtual void WriteInterfaceMethodDeclaration(InterfaceMethodDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.IsNew)
                writer.Write("new ");
            WriteReturnType(n.ReturnType, writer);
            writer.Write(" ");
            WriteIdentifier(n.Name, writer);
            if (n.TypeParameters != null)
                WriteVariantTypeParameterList(n.TypeParameters, writer);
            writer.Write("(");
            if (n.FormalParameters != null)
                WriteFormalParameterList(n.FormalParameters, writer);
            writer.Write(")");
            if (n.Constraints != null)
            {
                writer.Write(" ");
                WriteTypeParameterConstraintsClauses(n.Constraints, writer);
            }
            writer.Write(";\n");
        }

        public virtual void WriteInterfacePropertyDeclaration(InterfacePropertyDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.IsNew)
                writer.Write("new ");
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteIdentifier(n.Name, writer);
            writer.Write(" { ");
            WriteInterfaceAccessors(n.Accessors, writer);
            writer.Write(" }\n");
        }

        public virtual void WriteGetOnlyInterfaceAccessors(GetOnlyInterfaceAccessors n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceGetAccessor(n.Getter, writer);
        }

        public virtual void WriteSetOnlyInterfaceAccessors(SetOnlyInterfaceAccessors n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceSetAccessor(n.Setter, writer);
        }

        public virtual void WriteGetSetInterfaceAccessors(GetSetInterfaceAccessors n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceGetAccessor(n.Getter, writer);
            writer.Write(" ");
            WriteInterfaceSetAccessor(n.Setter, writer);
        }

        public virtual void WriteSetGetInterfaceAccessors(SetGetInterfaceAccessors n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteInterfaceSetAccessor(n.Setter, writer);
            writer.Write(" ");
            WriteInterfaceGetAccessor(n.Getter, writer);
        }

        public virtual void WriteInterfaceGetAccessor(InterfaceGetAccessor n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
            {
                WriteAttributes(n.Attributes, writer, true);
                writer.Write(" ");
            }
            writer.Write("get;");
        }

        public virtual void WriteInterfaceSetAccessor(InterfaceSetAccessor n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
            {
                WriteAttributes(n.Attributes, writer, true);
                writer.Write(" ");
            }
            writer.Write("set;");
        }

        public virtual void WriteInterfaceEventDeclaration(InterfaceEventDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.IsNew)
                writer.Write("new ");
            writer.Write("event ");
            WriteType(n.Type, writer);
            writer.Write(" ");
            WriteIdentifier(n.Name, writer);
            writer.Write(";\n");
        }

        public virtual void WriteInterfaceIndexerDeclaration(InterfaceIndexerDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.IsNew)
                writer.Write("new ");
            WriteType(n.Type, writer);
            writer.Write(" this[");
            WriteFormalParameterList(n.FormalParameters, writer);
            writer.Write("] { ");
            WriteInterfaceAccessors(n.Accessors, writer);
            writer.Write(" }\n");
        }
        #endregion

        #region P514 B.2.11 Enums
        public virtual void WriteEnumDeclaration(EnumDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteEnumModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            writer.Write("enum ");
            WriteIdentifier(n.Name, writer);
            if (n.Base != null)
            {
                writer.Write(" ");
                WriteEnumBase(n.Base, writer);
            }
            writer.Write("\n");
            WriteEnumBody(n.Body, writer, n.HasTrailingSemicolon ?? false);
        }

        public virtual void WriteEnumBase(EnumBase n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write(": ");
            WriteIntegralType(n.Type, writer);
        }

        public virtual void WriteEnumBody(EnumBody n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteEnumBody(n, writer, false);
        }

        public virtual void WriteEnumBody(EnumBody n, IndentedWriter writer, bool hasTrailingSemicolon)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.OpenCurlyBlock();
            if (n.Declarations != null)
            {
                WriteEnumMemberDeclarations(n.Declarations, writer);
                if (n.HasTrailingComma ?? false)
                    writer.Write(",");
                writer.Write("\n");
            }
            if (hasTrailingSemicolon)
                writer.CloseBlock(";");
            else
                writer.CloseCurlyBlock();
        }

        public virtual void WriteEnumModifiers(EnumModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteEnumModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewEnumModifier(NewEnumModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicEnumModifier(PublicEnumModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedEnumModifier(ProtectedEnumModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalEnumModifier(InternalEnumModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateEnumModifier(PrivateEnumModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }

        public virtual void WriteEnumMemberDeclarations(EnumMemberDeclarations n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(",\n");
                WriteEnumMemberDeclaration(n.Items[i], writer);
            }
        }

        public virtual void WriteEnumMemberDeclaration(EnumMemberDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            WriteIdentifier(n.Name, writer);
            if (n.Value != null)
            {
                writer.Write(" = ");
                WriteConstantExpression(n.Value, writer);
            }
        }
        #endregion

        #region P515 B.2.12 Delegates
        public virtual void WriteDelegateDeclaration(DelegateDeclaration n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Attributes != null)
                WriteAttributes(n.Attributes, writer);
            if (n.Modifiers != null)
            {
                WriteDelegateModifiers(n.Modifiers, writer);
                writer.Write(" ");
            }
            writer.Write("delegate ");
            WriteReturnType(n.ReturnType, writer);
            writer.Write(" ");
            WriteIdentifier(n.Name, writer);
            if (n.TypeParameters != null)
                WriteVariantTypeParameterList(n.TypeParameters, writer);
            writer.Write("(");
            if (n.FormalParameters != null)
                WriteFormalParameterList(n.FormalParameters, writer);
            writer.Write(")");
            if (n.Constraints != null)
            {
                writer.Write(" ");
                WriteTypeParameterConstraintsClauses(n.Constraints, writer);
            }
            writer.Write(";\n");
        }

        public virtual void WriteDelegateModifiers(DelegateModifiers n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(" ");
                WriteDelegateModifier(n.Items[i], writer);
            }
        }

        public virtual void WriteNewDelegateModifier(NewDelegateModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("new");
        }

        public virtual void WritePublicDelegateModifier(PublicDelegateModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("public");
        }

        public virtual void WriteProtectedDelegateModifier(ProtectedDelegateModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("protected");
        }

        public virtual void WriteInternalDelegateModifier(InternalDelegateModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("internal");
        }

        public virtual void WritePrivateDelegateModifier(PrivateDelegateModifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("private");
        }
        #endregion

        #region P515 B.2.13 Attributes
        public virtual void WriteGlobalAttributes(GlobalAttributes n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteGlobalAttributeSections(n.Sections, writer);
        }

        public virtual void WriteGlobalAttributeSections(GlobalAttributeSections n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (GlobalAttributeSection item in n.Items)
            {
                WriteGlobalAttributeSection(item, writer);
                writer.Write("\n");
            }
        }

        public virtual void WriteGlobalAttributeSection(GlobalAttributeSection n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("[");
            WriteGlobalAttributeTargetSpecifier(n.Specifier, writer);
            writer.Write(" ");
            WriteAttributeList(n.Attributes, writer);
            if (n.HasTrailingComma ?? false)
                writer.Write(",");
            writer.Write("]");
        }

        public virtual void WriteGlobalAttributeTargetSpecifier(GlobalAttributeTargetSpecifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteGlobalAttributeTarget(n.Target, writer);
            writer.Write(":");
        }

        public virtual void WriteAssemblyGlobalAttributeTarget(AssemblyGlobalAttributeTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("assembly");
        }

        public virtual void WriteModuleGlobalAttributeTarget(ModuleGlobalAttributeTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("module");
        }

        public virtual void WriteAttributes(Attributes n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteAttributes(n, writer, false);
        }

        public virtual void WriteAttributes(Attributes n, IndentedWriter writer, bool horizontally)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteAttributeSections(n.Sections, writer, horizontally);
        }

        public virtual void WriteAttributeSections(AttributeSections n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteAttributeSections(n, writer, false);
        }

        public virtual void WriteAttributeSections(AttributeSections n, IndentedWriter writer, bool horizontally)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            foreach (AttributeSection item in n.Items)
            {
                WriteAttributeSection(item, writer);
                if (!horizontally)
                    writer.Write("\n");
            }
        }

        public virtual void WriteAttributeSection(AttributeSection n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("[");
            if (n.Specifier != null)
            {
                WriteAttributeTargetSpecifier(n.Specifier, writer);
                writer.Write(" ");
            }
            WriteAttributeList(n.Attributes, writer);
            if (n.HasTrailingComma ?? false)
                writer.Write(",");
            writer.Write("]");
        }

        public virtual void WriteAttributeTargetSpecifier(AttributeTargetSpecifier n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteAttributeTarget(n.Target, writer);
            writer.Write(":");
        }

        public virtual void WriteFieldAttributeTarget(FieldAttributeTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("field");
        }

        public virtual void WriteEventAttributeTarget(EventAttributeTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("event");
        }

        public virtual void WriteMethodAttributeTarget(MethodAttributeTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("method");
        }

        public virtual void WriteParamAttributeTarget(ParamAttributeTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("param");
        }

        public virtual void WritePropertyAttributeTarget(PropertyAttributeTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("property");
        }

        public virtual void WriteReturnAttributeTarget(ReturnAttributeTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("return");
        }

        public virtual void WriteTypeAttributeTarget(TypeAttributeTarget n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("type");
        }

        public virtual void WriteAttributeList(AttributeList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteAttribute(n.Items[i], writer);
            }
        }

        public virtual void WriteAttribute(Attribute n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteAttributeName(n.Name, writer);
            if (n.Arguments != null)
                WriteAttributeArguments(n.Arguments, writer);
        }

        public virtual void WriteAttributeName(AttributeName n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteTypeName(n.Type, writer);
        }

        public virtual void WriteAttributeArguments(AttributeArguments n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            writer.Write("(");
            if (n.Positional != null)
                WritePositionalArgumentList(n.Positional, writer);
            if (n.Named != null)
            {
                if (n.Positional != null)
                    writer.Write(", ");
                WriteNamedArgumentList(n.Named, writer);
            }
            writer.Write(")");
        }

        public virtual void WritePositionalArgumentList(PositionalArgumentList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WritePositionalArgument(n.Items[i], writer);
            }
        }

        public virtual void WritePositionalArgument(PositionalArgument n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            if (n.Name != null)
            {
                WriteArgumentName(n.Name, writer);
                writer.Write(" ");
            }
            WriteAttributeArgumentExpression(n.Value, writer);
        }

        public virtual void WriteNamedArgumentList(NamedArgumentList n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            for (int i = 0; i < n.Items.Count; i++)
            {
                if (i > 0)
                    writer.Write(", ");
                WriteNamedArgument(n.Items[i], writer);
            }
        }

        public virtual void WriteNamedArgument(NamedArgument n, IndentedWriter writer)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteIdentifier(n.Name, writer);
            writer.Write(" = ");
            WriteAttributeArgumentExpression(n.Value, writer);
        }

        public virtual void WriteAttributeArgumentExpression(AttributeArgumentExpression n, IndentedWriter writer, int d)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (writer == null)
                throw new ArgumentNullException(nameof(writer));
            WriteExpression(n.Value, writer);
        }
        #endregion
    }
}
